Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bbe4634535 | |||
| e7b8f7681c | |||
| 64168d103d | |||
| 600a321f49 | |||
| e753f4df32 | |||
| cbe7353122 | |||
| de5682a960 | |||
| b451399323 | |||
| e547aa32ca | |||
| 3fe9d762da | |||
| 20b53596e2 |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"homepage": "https://www.curseforge.com/minecraft/mc-mods/electroblobs-wizardry",
|
||||
"promos": {
|
||||
"1.12.2-latest": "4.3.15",
|
||||
"1.12.2-recommended": "4.3.15"
|
||||
"1.12.2-latest": "4.3.16",
|
||||
"1.12.2-recommended": "4.3.16"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ apply plugin: org.ajoberstar.grgit.gradle.GrgitPlugin
|
||||
apply plugin: 'wtf.gofancy.fancygradle'
|
||||
|
||||
|
||||
version = "4.3.15"
|
||||
version = "4.3.16"
|
||||
group= "electroblob.wizardry"// http://maven.apache.org/guides/mini/guide-naming-conventions.html
|
||||
archivesBaseName = "ElectroblobsWizardry"
|
||||
|
||||
|
||||
@@ -43,6 +43,10 @@ public class CommonProxy {
|
||||
|
||||
public void registerRenderers(){}
|
||||
|
||||
public void registerItemColorHandlers(){}
|
||||
|
||||
public void registerModelProperties(){}
|
||||
|
||||
public void initialiseLayers(){}
|
||||
|
||||
public void initialiseAnimations(){}
|
||||
@@ -175,6 +179,8 @@ public class CommonProxy {
|
||||
|
||||
public void handleConquerShrinePacket(PacketConquerShrine.Message message){}
|
||||
|
||||
public void handleBombExplosionPacket(PacketBombExplosion.Message message){}
|
||||
|
||||
// SECTION Misc
|
||||
// ===============================================================================================================
|
||||
|
||||
|
||||
@@ -355,6 +355,8 @@ public final class Settings {
|
||||
* velocity-based one.
|
||||
*/
|
||||
public boolean replaceVanillaFallDamage = true;
|
||||
/** <b>[Synchronised]</b> Whether spell book colors are only shown when the player has the Archivist's Eyeglass equipped. */
|
||||
public boolean spellBookColorsRequireArchivistsEyeglass = false;
|
||||
/** <b>[Synchronised]</b> Chance of 'misreading' an undiscovered spell and triggering a forfeit instead. */
|
||||
public double forfeitChance = 0.2;
|
||||
/** <b>[Synchronised]</b> Progression requirements for upgrading a wand to each tier. */
|
||||
@@ -461,6 +463,8 @@ public final class Settings {
|
||||
public static final String DEFAULT_HUD_SKIN_KEY = "default"; // Defined here so it's not in a client-only class.
|
||||
/** <b>[Client-only]</b> The string identifier of the skin used for the spell HUD. */
|
||||
public String spellHUDSkin = DEFAULT_HUD_SKIN_KEY;
|
||||
/** <b>[Client-only]</b> Whether to show elemental colors on spell books for discovered spells. */
|
||||
public boolean spellBookColors = true;
|
||||
|
||||
/** Set of constants for each of the eight positions that the spell HUD can be in. */
|
||||
public enum GuiPosition {
|
||||
@@ -1103,6 +1107,13 @@ public final class Settings {
|
||||
replaceVanillaFallDamage = property.getBoolean();
|
||||
propOrder.add(property.getName());
|
||||
|
||||
property = config.get(TWEAKS_CATEGORY, "spellBookColorsRequireArchivistsEyeglass", false,
|
||||
"If true, spell book colors are only shown when the player has the charm of spell discovery equipped.");
|
||||
property.setLanguageKey("config." + Wizardry.MODID + ".spell_book_colors_require_charm");
|
||||
Wizardry.proxy.setToNamedBooleanEntry(property);
|
||||
spellBookColorsRequireArchivistsEyeglass = property.getBoolean();
|
||||
propOrder.add(property.getName());
|
||||
|
||||
property = config.get(TWEAKS_CATEGORY, "blindnessTweak", true,
|
||||
"Whether to tweak the blindness effect to reduce follow distance when used on non-players. This automatically disables itself in favour of Potion Core's implementation if installed.");
|
||||
property.setLanguageKey("config." + Wizardry.MODID + ".blindness_tweak");
|
||||
@@ -1213,7 +1224,7 @@ public final class Settings {
|
||||
bookshelfSearchRadius = property.getInt();
|
||||
propOrder.add(property.getName());
|
||||
|
||||
property = config.get(TWEAKS_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.",
|
||||
property = config.get(TWEAKS_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. To specify metadata, use the format 'modid:item:meta value'. For example, 'minecraft:wool:1 5'. If no metadata is given, any metadata will be accepted.",
|
||||
Pattern.compile("[A-Za-z0-9:_]+ [0-9]+"));
|
||||
property.setLanguageKey("config." + Wizardry.MODID + ".currency_items");
|
||||
propOrder.add(property.getName());
|
||||
@@ -1487,6 +1498,14 @@ public final class Settings {
|
||||
Wizardry.proxy.setToNamedBooleanEntry(property);
|
||||
showChargeMeter = property.getBoolean();
|
||||
propOrder.add(property.getName());
|
||||
|
||||
property = config.get(CLIENT_CATEGORY, "spellBookColors", true, "Whether to show elemental colors on spell books for discovered spells.");
|
||||
property.setLanguageKey("config." + Wizardry.MODID + ".spell_book_colors");
|
||||
property.setRequiresWorldRestart(false);
|
||||
Wizardry.proxy.setToNamedBooleanEntry(property);
|
||||
spellBookColors = property.getBoolean();
|
||||
propOrder.add(property.getName());
|
||||
|
||||
property = config.get(CLIENT_CATEGORY, "loadHandbook", true, "Whether to initialise the in-game handbook. Setting this to false will brick the in-game handbook, but it might help if you have startup crashes.");
|
||||
property.setLanguageKey("config." + Wizardry.MODID + ".load_handbook");
|
||||
property.setRequiresWorldRestart(false);
|
||||
@@ -1817,16 +1836,46 @@ public final class Settings {
|
||||
|
||||
string = string.toLowerCase(Locale.ROOT).trim();
|
||||
|
||||
String[] itemArgs = string.split(":");
|
||||
String item;
|
||||
short meta;
|
||||
|
||||
try {
|
||||
meta = Short.parseShort(itemArgs[itemArgs.length-1]);
|
||||
item = String.join(":", Arrays.copyOfRange(itemArgs, 0, itemArgs.length-1));
|
||||
}catch(NumberFormatException e){ // If no metadata is specified
|
||||
meta = OreDictionary.WILDCARD_VALUE;
|
||||
int lastColon = string.lastIndexOf(':');
|
||||
|
||||
if (lastColon > -1 && lastColon < string.length() - 1) { // if there is a colon and it's not the last char
|
||||
String metaString = string.substring(lastColon + 1);
|
||||
try {
|
||||
short parsedMeta = Short.parseShort(metaString);
|
||||
String itemString = string.substring(0, lastColon);
|
||||
|
||||
// If itemString has no colon, it could be 'item:meta' or 'namespace:numeric_path'.
|
||||
// e.g., 'wool:1' vs 'mod:123'. We want to support 'wool:1' as item 'wool' with meta 1.
|
||||
// We can't reliably distinguish the two cases without knowing all namespaces, so we have to use
|
||||
// a heuristic. The original code favoured the 'item:meta' interpretation, let's stick with that.
|
||||
// The issue was with 'namespace:numeric_path' which this logic now handles.
|
||||
if (itemString.indexOf(':') == -1) {
|
||||
item = itemString;
|
||||
meta = parsedMeta;
|
||||
} else {
|
||||
// Disambiguate things like 'mod:123:4' (item 'mod:123' with meta 4) vs 'mod:item:123' (item 'mod:item' with meta 123)
|
||||
// If the bit before the last colon is a valid resource location, it's probably item:meta
|
||||
try {
|
||||
new ResourceLocation(itemString);
|
||||
item = itemString;
|
||||
meta = parsedMeta;
|
||||
} catch (Exception e) {
|
||||
item = string;
|
||||
meta = OreDictionary.WILDCARD_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
// The part after colon is not a number, so it's part of the name
|
||||
item = string;
|
||||
meta = OreDictionary.WILDCARD_VALUE;
|
||||
}
|
||||
} else {
|
||||
item = string;
|
||||
meta = OreDictionary.WILDCARD_VALUE;
|
||||
}
|
||||
|
||||
return Pair.of(new ResourceLocation(item), meta);
|
||||
|
||||
@@ -82,7 +82,7 @@ public class Wizardry {
|
||||
* 1.x.x represents Minecraft 1.7.x versions, 2.x.x represents Minecraft 1.10.x versions, 3.x.x represents Minecraft
|
||||
* 1.11.x versions, and so on.
|
||||
*/
|
||||
public static final String VERSION = "4.3.15";
|
||||
public static final String VERSION = "4.3.16";
|
||||
|
||||
/**
|
||||
* Json file used by Forge's built-in <a href="https://mcforge.readthedocs.io/en/1.12.x/gettingstarted/autoupdate/">update checker</a>.
|
||||
@@ -198,6 +198,8 @@ public class Wizardry {
|
||||
// Client-side stuff (via proxies)
|
||||
proxy.initGuiBits();
|
||||
proxy.registerParticles();
|
||||
proxy.registerItemColorHandlers();
|
||||
proxy.registerModelProperties();
|
||||
proxy.registerSoundEventListener();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package electroblob.wizardry.client;
|
||||
|
||||
import electroblob.wizardry.CommonProxy;
|
||||
import electroblob.wizardry.Settings;
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.block.BlockBookshelf;
|
||||
import electroblob.wizardry.client.animation.ActionAnimation;
|
||||
@@ -19,6 +18,8 @@ import electroblob.wizardry.client.model.ModelRobeArmour;
|
||||
import electroblob.wizardry.client.model.ModelSageArmour;
|
||||
import electroblob.wizardry.client.model.ModelWizardArmour;
|
||||
import electroblob.wizardry.client.particle.*;
|
||||
import electroblob.wizardry.constants.Element;
|
||||
import electroblob.wizardry.registry.WizardryItems;
|
||||
import electroblob.wizardry.client.particle.ParticleWizardry.IWizardryParticleFactory;
|
||||
import electroblob.wizardry.client.renderer.RenderSpectralGolem;
|
||||
import electroblob.wizardry.client.renderer.entity.*;
|
||||
@@ -38,6 +39,7 @@ 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.ItemArtefact;
|
||||
import electroblob.wizardry.item.ItemScroll;
|
||||
import electroblob.wizardry.item.ItemSpellBook;
|
||||
import electroblob.wizardry.item.ItemWand;
|
||||
@@ -715,6 +717,65 @@ public class ClientProxy extends CommonProxy {
|
||||
}else Wizardry.logger.warn("Received a PacketConquerShrine, but there was no shrine core at the position sent");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleBombExplosionPacket(PacketBombExplosion.Message message){
|
||||
|
||||
net.minecraft.world.World world = Minecraft.getMinecraft().world;
|
||||
double x = message.x, y = message.y, z = message.z;
|
||||
float blastMultiplier = message.blastMultiplier;
|
||||
|
||||
switch(message.bombType){
|
||||
|
||||
case PacketBombExplosion.FIREBOMB:
|
||||
ParticleBuilder.create(Type.FLASH).pos(x, y, z).scale(5 * blastMultiplier).clr(1, 0.6f, 0).spawn(world);
|
||||
for(int i = 0; i < 60 * blastMultiplier; i++){
|
||||
ParticleBuilder.create(Type.MAGIC_FIRE, world.rand, x, y, z, 2 * blastMultiplier, false)
|
||||
.time(10 + world.rand.nextInt(4)).scale(2 + world.rand.nextFloat()).spawn(world);
|
||||
ParticleBuilder.create(Type.DARK_MAGIC, world.rand, x, y, z, 2 * blastMultiplier, false)
|
||||
.clr(1.0f, 0.2f + world.rand.nextFloat() * 0.4f, 0.0f).spawn(world);
|
||||
}
|
||||
world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, x, y, z, 0, 0, 0);
|
||||
break;
|
||||
|
||||
case PacketBombExplosion.POISON_BOMB:
|
||||
ParticleBuilder.create(Type.FLASH).pos(x, y, z).scale(5 * blastMultiplier)
|
||||
.clr(0.2f + world.rand.nextFloat() * 0.3f, 0.6f, 0.0f).spawn(world);
|
||||
for(int i = 0; i < 60 * blastMultiplier; i++){
|
||||
ParticleBuilder.create(Type.SPARKLE, world.rand, x, y, z, 2 * blastMultiplier, false).time(35)
|
||||
.scale(2).clr(0.2f + world.rand.nextFloat() * 0.3f, 0.6f, 0.0f).spawn(world);
|
||||
ParticleBuilder.create(Type.DARK_MAGIC, world.rand, x, y, z, 2 * blastMultiplier, false)
|
||||
.clr(0.2f + world.rand.nextFloat() * 0.2f, 0.8f, 0.0f).spawn(world);
|
||||
}
|
||||
world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, x, y, z, 0, 0, 0);
|
||||
break;
|
||||
|
||||
case PacketBombExplosion.SMOKE_BOMB:
|
||||
ParticleBuilder.create(Type.FLASH).pos(x, y, z).scale(5 * blastMultiplier).clr(0, 0, 0).spawn(world);
|
||||
world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, x, y, z, 0, 0, 0);
|
||||
for(int i = 0; i < 60 * blastMultiplier; i++){
|
||||
float brightness = world.rand.nextFloat() * 0.1f + 0.1f;
|
||||
ParticleBuilder.create(Type.CLOUD, world.rand, x, y, z, 2 * blastMultiplier, false)
|
||||
.clr(brightness, brightness, brightness).time(80 + world.rand.nextInt(12)).shaded(true).spawn(world);
|
||||
brightness = world.rand.nextFloat() * 0.3f;
|
||||
ParticleBuilder.create(Type.DARK_MAGIC, world.rand, x, y, z, 2 * blastMultiplier, false)
|
||||
.clr(brightness, brightness, brightness).spawn(world);
|
||||
}
|
||||
break;
|
||||
|
||||
case PacketBombExplosion.SPARK_BOMB:
|
||||
ParticleBuilder.spawnShockParticles(world, x, y, z);
|
||||
for(int id : message.secondaryTargetIDs){
|
||||
net.minecraft.entity.Entity target = world.getEntityByID(id);
|
||||
if(target instanceof net.minecraft.entity.EntityLivingBase){
|
||||
ParticleBuilder.create(Type.LIGHTNING).pos(x, y, z).target(target).spawn(world);
|
||||
ParticleBuilder.spawnShockParticles(world, target.posX,
|
||||
target.posY + target.height / 2, target.posZ);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Rendering
|
||||
// ===============================================================================================================
|
||||
|
||||
@@ -877,4 +938,51 @@ public class ClientProxy extends CommonProxy {
|
||||
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityImbuementAltar.class, new RenderImbuementAltar());
|
||||
|
||||
}
|
||||
|
||||
public void registerItemColorHandlers() {
|
||||
// Spell book overlay textures are now per-element, so no runtime tinting is needed.
|
||||
}
|
||||
|
||||
public void registerModelProperties() {
|
||||
Item spellBook = WizardryItems.spell_book;
|
||||
|
||||
spellBook.addPropertyOverride(new ResourceLocation(Wizardry.MODID, "discovered"), (stack, world, entity) -> {
|
||||
if (!Wizardry.settings.spellBookColors) return 0.0f;
|
||||
|
||||
boolean discovered = shouldDisplayDiscovered(Spell.byMetadata(stack.getMetadata()), stack);
|
||||
|
||||
if(discovered && Wizardry.settings.spellBookColorsRequireArchivistsEyeglass){
|
||||
// Entity can be null so we have to check
|
||||
if(entity instanceof EntityPlayer){
|
||||
return ItemArtefact.isArtefactActive((EntityPlayer)entity, WizardryItems.charm_spell_discovery) ? 1.0f : 0.0f;
|
||||
}
|
||||
// If there's no entity, there's no charm, so no colour
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
return discovered ? 1.0f : 0.0f;
|
||||
});
|
||||
|
||||
// Returns ordinal+1 for each element (1=MAGIC through 8=HEALING), or 0 if not yet discovered.
|
||||
// Drives per-element bookmark texture selection via model overrides in spell_book.json.
|
||||
spellBook.addPropertyOverride(new ResourceLocation(Wizardry.MODID, "element"), (stack, world, entity) -> {
|
||||
if (!Wizardry.settings.spellBookColors) return 0.0f;
|
||||
|
||||
Spell spell = Spell.byMetadata(stack.getMetadata());
|
||||
boolean discovered = shouldDisplayDiscovered(spell, stack);
|
||||
|
||||
if(!discovered) return 0.0f;
|
||||
|
||||
if(Wizardry.settings.spellBookColorsRequireArchivistsEyeglass){
|
||||
if(entity instanceof EntityPlayer){
|
||||
if(!ItemArtefact.isArtefactActive((EntityPlayer)entity, WizardryItems.charm_spell_discovery)) return 0.0f;
|
||||
} else {
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
Element element = spell.getElement();
|
||||
return element == null ? 0.0f : (float)(element.ordinal() + 1);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package electroblob.wizardry.client;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.renderer.overlay.RenderBlinkEffect;
|
||||
import electroblob.wizardry.data.DispenserCastingData;
|
||||
import electroblob.wizardry.data.SpellEmitterData;
|
||||
@@ -13,7 +14,6 @@ import electroblob.wizardry.spell.SixthSense;
|
||||
import electroblob.wizardry.spell.SlowTime;
|
||||
import electroblob.wizardry.spell.Transience;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiMainMenu;
|
||||
import net.minecraft.client.gui.ScaledResolution;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
@@ -31,6 +31,9 @@ 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 net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
import net.minecraftforge.event.entity.player.ItemTooltipEvent;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -196,6 +199,15 @@ public final class WizardryClientEventHandler {
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onItemTooltip(ItemTooltipEvent event) {
|
||||
if (event.getItemStack().getItem() == WizardryItems.charm_spell_discovery) {
|
||||
if (Wizardry.settings.spellBookColorsRequireArchivistsEyeglass) {
|
||||
event.getToolTip().add(TextFormatting.GRAY + I18n.format("item.ebwizardry:charm_spell_discovery.desc.color"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders an overlay across the entire screen.
|
||||
* @param resolution The screen resolution
|
||||
|
||||
@@ -515,12 +515,13 @@ public class GuiArcaneWorkbench extends GuiContainer {
|
||||
@Override
|
||||
protected void keyTyped(char typedChar, int keyCode) throws IOException {
|
||||
|
||||
if(this.searchNeedsClearing){
|
||||
this.searchNeedsClearing = false;
|
||||
if(this.searchNeedsClearing){
|
||||
this.searchNeedsClearing = false;
|
||||
this.searchField.setText("");
|
||||
}
|
||||
|
||||
if(this.searchField.textboxKeyTyped(typedChar, keyCode)){
|
||||
// Allow exiting the GUI by pressing the inventory button. Does not work if bookshelves are present by default
|
||||
if(this.searchField.getVisible() && this.searchField.textboxKeyTyped(typedChar, keyCode)){
|
||||
arcaneWorkbenchContainer.setSearchText(searchField.getText().toLowerCase(Locale.ROOT));
|
||||
}else{
|
||||
super.keyTyped(typedChar, keyCode);
|
||||
@@ -1062,4 +1063,4 @@ public class GuiArcaneWorkbench extends GuiContainer {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import electroblob.wizardry.enchantment.Imbuement;
|
||||
import electroblob.wizardry.entity.living.ISummonedCreature;
|
||||
import electroblob.wizardry.event.SpellCastEvent;
|
||||
import electroblob.wizardry.event.SpellCastEvent.Source;
|
||||
import electroblob.wizardry.item.ItemWand;
|
||||
import electroblob.wizardry.packet.PacketCastContinuousSpell;
|
||||
import electroblob.wizardry.packet.PacketPlayerSync;
|
||||
import electroblob.wizardry.packet.WizardryPacketHandler;
|
||||
@@ -356,20 +355,20 @@ public class WizardData implements INBTSerializable<NBTTagCompound> {
|
||||
|
||||
// For each item in the player's inventory
|
||||
for(ItemStack stack : player.inventory.mainInventory){
|
||||
updateImbutedItem(stack, activeImbuements);
|
||||
updateImbuedItem(stack, activeImbuements);
|
||||
}
|
||||
for(ItemStack stack : player.inventory.armorInventory){
|
||||
updateImbutedItem(stack, activeImbuements);
|
||||
updateImbuedItem(stack, activeImbuements);
|
||||
}
|
||||
for(ItemStack stack : player.inventory.offHandInventory){
|
||||
updateImbutedItem(stack, activeImbuements);
|
||||
updateImbuedItem(stack, activeImbuements);
|
||||
}
|
||||
|
||||
// Removes all imbuements from the map that are no longer active
|
||||
this.imbuementDurations.keySet().retainAll(activeImbuements);
|
||||
}
|
||||
|
||||
private void updateImbutedItem(ItemStack stack, Set<Imbuement> activeImbuements){
|
||||
private void updateImbuedItem(ItemStack stack, Set<Imbuement> activeImbuements){
|
||||
|
||||
if(stack.isItemEnchanted()){
|
||||
|
||||
@@ -466,7 +465,7 @@ public class WizardData implements INBTSerializable<NBTTagCompound> {
|
||||
|
||||
if(this.castCommandSpell != null && this.castCommandSpell.isContinuous){
|
||||
|
||||
if(castCommandTick >= castCommandDuration){
|
||||
if(castCommandTick > castCommandDuration){
|
||||
this.stopCastingContinuousSpell();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import electroblob.wizardry.packet.PacketBombExplosion;
|
||||
import electroblob.wizardry.packet.WizardryPacketHandler;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import electroblob.wizardry.util.EntityUtils;
|
||||
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.entity.EntityLivingBase;
|
||||
import net.minecraft.util.EnumParticleTypes;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.common.network.NetworkRegistry;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -29,41 +29,28 @@ public class EntityFirebomb extends EntityBomb {
|
||||
|
||||
@Override
|
||||
protected void onImpact(RayTraceResult rayTrace){
|
||||
|
||||
Entity entityHit = rayTrace.entityHit;
|
||||
|
||||
if(entityHit != null){
|
||||
// This is if the firebomb gets a direct hit
|
||||
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(Spells.firebomb.getProperty(Spell.BURN_DURATION).intValue());
|
||||
}
|
||||
|
||||
// Particle effect
|
||||
if(world.isRemote){
|
||||
|
||||
ParticleBuilder.create(Type.FLASH).pos(this.getPositionVector()).scale(5 * blastMultiplier).clr(1, 0.6f, 0)
|
||||
.spawn(world);
|
||||
|
||||
for(int i = 0; i < 60 * blastMultiplier; i++){
|
||||
|
||||
ParticleBuilder.create(Type.MAGIC_FIRE, rand, posX, posY, posZ, 2*blastMultiplier, false)
|
||||
.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);
|
||||
}
|
||||
|
||||
this.world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, this.posX, this.posY, this.posZ, 0, 0, 0);
|
||||
}
|
||||
|
||||
if(!this.world.isRemote){
|
||||
|
||||
Entity entityHit = rayTrace.entityHit;
|
||||
|
||||
if(entityHit != null){
|
||||
// This is if the firebomb gets a direct hit
|
||||
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(Spells.firebomb.getProperty(Spell.BURN_DURATION).intValue());
|
||||
}
|
||||
|
||||
// Notify clients to play the explosion effect
|
||||
WizardryPacketHandler.net.sendToAllAround(
|
||||
new PacketBombExplosion.Message(PacketBombExplosion.FIREBOMB, posX, posY, posZ, blastMultiplier),
|
||||
new NetworkRegistry.TargetPoint(world.provider.getDimension(), posX, posY, posZ, 64));
|
||||
|
||||
this.playSound(WizardrySounds.ENTITY_FIREBOMB_SMASH, 1.5F, rand.nextFloat() * 0.4F + 0.6F);
|
||||
this.playSound(WizardrySounds.ENTITY_FIREBOMB_FIRE, 1, 1);
|
||||
|
||||
@@ -82,9 +69,9 @@ public class EntityFirebomb extends EntityBomb {
|
||||
target.setFire(Spells.firebomb.getProperty(Spell.BURN_DURATION).intValue());
|
||||
}
|
||||
}
|
||||
|
||||
this.setDead();
|
||||
}
|
||||
|
||||
this.setDead();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import electroblob.wizardry.packet.PacketBombExplosion;
|
||||
import electroblob.wizardry.packet.WizardryPacketHandler;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import electroblob.wizardry.util.EntityUtils;
|
||||
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.entity.EntityLivingBase;
|
||||
import net.minecraft.init.MobEffects;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.util.EnumParticleTypes;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.common.network.NetworkRegistry;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -31,44 +31,30 @@ public class EntityPoisonBomb extends EntityBomb {
|
||||
|
||||
@Override
|
||||
protected void onImpact(RayTraceResult rayTrace){
|
||||
|
||||
Entity entityHit = rayTrace.entityHit;
|
||||
|
||||
if(entityHit != null){
|
||||
// This is if the poison bomb gets a direct hit
|
||||
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,
|
||||
Spells.poison_bomb.getProperty(Spell.DIRECT_EFFECT_DURATION).intValue(),
|
||||
Spells.poison_bomb.getProperty(Spell.DIRECT_EFFECT_STRENGTH).intValue()));
|
||||
}
|
||||
|
||||
// Particle effect
|
||||
if(world.isRemote){
|
||||
|
||||
ParticleBuilder.create(Type.FLASH).pos(this.getPositionVector()).scale(5 * blastMultiplier)
|
||||
.clr(0.2f + rand.nextFloat() * 0.3f, 0.6f, 0.0f).spawn(world);
|
||||
|
||||
for(int i = 0; i < 60 * blastMultiplier; i++){
|
||||
|
||||
ParticleBuilder.create(Type.SPARKLE, rand, posX, posY, posZ, 2*blastMultiplier, false).time(35)
|
||||
.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);
|
||||
}
|
||||
// Spawning this after the other particles fixes the rendering colour bug. It's a bit of a cheat, but it
|
||||
// works pretty well.
|
||||
this.world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, this.posX, this.posY, this.posZ, 0, 0, 0);
|
||||
}
|
||||
|
||||
if(!this.world.isRemote){
|
||||
|
||||
Entity entityHit = rayTrace.entityHit;
|
||||
|
||||
if(entityHit != null){
|
||||
// This is if the poison bomb gets a direct hit
|
||||
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,
|
||||
Spells.poison_bomb.getProperty(Spell.DIRECT_EFFECT_DURATION).intValue(),
|
||||
Spells.poison_bomb.getProperty(Spell.DIRECT_EFFECT_STRENGTH).intValue()));
|
||||
}
|
||||
|
||||
// Notify clients to play the explosion effect
|
||||
WizardryPacketHandler.net.sendToAllAround(
|
||||
new PacketBombExplosion.Message(PacketBombExplosion.POISON_BOMB, posX, posY, posZ, blastMultiplier),
|
||||
new NetworkRegistry.TargetPoint(world.provider.getDimension(), posX, posY, posZ, 64));
|
||||
|
||||
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);
|
||||
|
||||
@@ -88,8 +74,8 @@ public class EntityPoisonBomb extends EntityBomb {
|
||||
Spells.poison_bomb.getProperty(Spell.SPLASH_EFFECT_STRENGTH).intValue()));
|
||||
}
|
||||
}
|
||||
|
||||
this.setDead();
|
||||
}
|
||||
|
||||
this.setDead();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import electroblob.wizardry.packet.PacketBombExplosion;
|
||||
import electroblob.wizardry.packet.WizardryPacketHandler;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import electroblob.wizardry.util.EntityUtils;
|
||||
import electroblob.wizardry.util.ParticleBuilder;
|
||||
import electroblob.wizardry.util.ParticleBuilder.Type;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.init.MobEffects;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.util.EnumParticleTypes;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.common.network.NetworkRegistry;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -29,27 +29,13 @@ public class EntitySmokeBomb extends EntityBomb {
|
||||
@Override
|
||||
protected void onImpact(RayTraceResult rayTrace){
|
||||
|
||||
// Particle effect
|
||||
if(world.isRemote){
|
||||
|
||||
ParticleBuilder.create(Type.FLASH).pos(this.getPositionVector()).scale(5 * blastMultiplier).clr(0, 0, 0).spawn(world);
|
||||
|
||||
this.world.spawnParticle(EnumParticleTypes.EXPLOSION_LARGE, this.posX, this.posY, this.posZ, 0, 0, 0);
|
||||
|
||||
for(int i = 0; i < 60 * blastMultiplier; i++){
|
||||
|
||||
float brightness = rand.nextFloat() * 0.1f + 0.1f;
|
||||
ParticleBuilder.create(Type.CLOUD, rand, posX, posY, posZ, 2*blastMultiplier, false)
|
||||
.clr(brightness, brightness, brightness).time(80 + this.rand.nextInt(12)).shaded(true).spawn(world);
|
||||
|
||||
brightness = rand.nextFloat() * 0.3f;
|
||||
ParticleBuilder.create(Type.DARK_MAGIC, rand, posX, posY, posZ, 2*blastMultiplier, false)
|
||||
.clr(brightness, brightness, brightness).spawn(world);
|
||||
}
|
||||
}
|
||||
|
||||
if(!this.world.isRemote){
|
||||
|
||||
// Notify clients to play the explosion effect
|
||||
WizardryPacketHandler.net.sendToAllAround(
|
||||
new PacketBombExplosion.Message(PacketBombExplosion.SMOKE_BOMB, posX, posY, posZ, blastMultiplier),
|
||||
new NetworkRegistry.TargetPoint(world.provider.getDimension(), posX, posY, posZ, 64));
|
||||
|
||||
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);
|
||||
|
||||
@@ -65,8 +51,8 @@ public class EntitySmokeBomb extends EntityBomb {
|
||||
target.addPotionEffect(new PotionEffect(MobEffects.BLINDNESS, duration, 0));
|
||||
}
|
||||
}
|
||||
|
||||
this.setDead();
|
||||
}
|
||||
|
||||
this.setDead();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import electroblob.wizardry.packet.PacketBombExplosion;
|
||||
import electroblob.wizardry.packet.WizardryPacketHandler;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
@@ -13,7 +15,9 @@ import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.common.network.NetworkRegistry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class EntitySparkBomb extends EntityBomb {
|
||||
@@ -31,47 +35,37 @@ public class EntitySparkBomb extends EntityBomb {
|
||||
|
||||
@Override
|
||||
protected void onImpact(RayTraceResult rayTrace){
|
||||
|
||||
this.playSound(WizardrySounds.ENTITY_SPARK_BOMB_HIT_BLOCK, 0.5f, 0.5f);
|
||||
|
||||
Entity entityHit = rayTrace.entityHit;
|
||||
if(!this.world.isRemote){
|
||||
|
||||
if(entityHit != null){
|
||||
// This is if the spark bomb gets a direct hit
|
||||
float damage = Spells.spark_bomb.getProperty(Spell.DIRECT_DAMAGE).floatValue() * damageMultiplier;
|
||||
Entity entityHit = rayTrace.entityHit;
|
||||
|
||||
this.playSound(WizardrySounds.ENTITY_SPARK_BOMB_HIT, 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
|
||||
if(entityHit != null){
|
||||
// This is if the spark bomb gets a direct hit
|
||||
float damage = Spells.spark_bomb.getProperty(Spell.DIRECT_DAMAGE).floatValue() * damageMultiplier;
|
||||
|
||||
entityHit.attackEntityFrom(
|
||||
MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.SHOCK).setProjectile(),
|
||||
damage);
|
||||
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(),
|
||||
damage);
|
||||
}
|
||||
|
||||
// Particle effect
|
||||
if(world.isRemote){
|
||||
ParticleBuilder.spawnShockParticles(world, posX, posY + height/2, posZ);
|
||||
}
|
||||
double seekerRange = Spells.spark_bomb.getProperty(Spell.EFFECT_RADIUS).doubleValue() * blastMultiplier;
|
||||
|
||||
double seekerRange = Spells.spark_bomb.getProperty(Spell.EFFECT_RADIUS).doubleValue() * blastMultiplier;
|
||||
List<EntityLivingBase> targets = EntityUtils.getLivingWithinRadius(seekerRange, this.posX, this.posY,
|
||||
this.posZ, this.world);
|
||||
|
||||
List<EntityLivingBase> targets = EntityUtils.getLivingWithinRadius(seekerRange, this.posX, this.posY,
|
||||
this.posZ, this.world);
|
||||
List<Integer> secondaryTargetIDs = new ArrayList<>();
|
||||
|
||||
for(int i = 0; i < Math.min(targets.size(), Spells.spark_bomb.getProperty(SECONDARY_MAX_TARGETS).intValue()); 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)).isCreative());
|
||||
boolean flag = targets.get(i) != entityHit && targets.get(i) != this.getThrower()
|
||||
&& !(targets.get(i) instanceof EntityPlayer
|
||||
&& ((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.playerID) flag = false;
|
||||
|
||||
if(flag){
|
||||
|
||||
EntityLivingBase target = targets.get(i);
|
||||
|
||||
if(!this.world.isRemote){
|
||||
if(flag){
|
||||
EntityLivingBase target = targets.get(i);
|
||||
|
||||
target.playSound(WizardrySounds.ENTITY_SPARK_BOMB_CHAIN, 1.0F, rand.nextFloat() * 0.4F + 1.5F);
|
||||
|
||||
@@ -79,11 +73,18 @@ public class EntitySparkBomb extends EntityBomb {
|
||||
MagicDamage.causeIndirectMagicDamage(this, this.getThrower(), DamageType.SHOCK),
|
||||
Spells.spark_bomb.getProperty(Spell.SPLASH_DAMAGE).floatValue() * damageMultiplier);
|
||||
|
||||
}else{
|
||||
ParticleBuilder.create(Type.LIGHTNING).pos(this.getPositionVector()).target(target).spawn(world);
|
||||
ParticleBuilder.spawnShockParticles(world, target.posX, target.posY + target.height/2, target.posZ);
|
||||
secondaryTargetIDs.add(target.getEntityId());
|
||||
}
|
||||
}
|
||||
|
||||
// Notify clients to play the explosion effect, including lightning arcs to secondary targets
|
||||
int[] idArray = secondaryTargetIDs.stream().mapToInt(Integer::intValue).toArray();
|
||||
WizardryPacketHandler.net.sendToAllAround(
|
||||
new PacketBombExplosion.Message(PacketBombExplosion.SPARK_BOMB, posX, posY + height / 2, posZ,
|
||||
blastMultiplier, idArray),
|
||||
new NetworkRegistry.TargetPoint(world.provider.getDimension(), posX, posY, posZ, 64));
|
||||
|
||||
this.playSound(WizardrySounds.ENTITY_SPARK_BOMB_HIT_BLOCK, 0.5f, 0.5f);
|
||||
}
|
||||
|
||||
this.setDead();
|
||||
|
||||
@@ -160,12 +160,21 @@ public class ItemScroll extends Item implements ISpellCastingItem, IWorkbenchIte
|
||||
|
||||
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();
|
||||
|
||||
SpellModifiers modifiers;
|
||||
|
||||
if(WizardData.get(player) != null){
|
||||
modifiers = WizardData.get(player).itemCastingModifiers;
|
||||
}else{
|
||||
modifiers = new SpellModifiers();
|
||||
}
|
||||
|
||||
int castingTick = stack.getMaxItemUseDuration() - count;
|
||||
|
||||
// Continuous spells (these must check if they can be cast each tick since the mana changes)
|
||||
// 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)){
|
||||
// Do not check canCast() on tick 0 as it is already done in onItemRightClick() and would duplicate modifiers
|
||||
if(spell.isContinuous && (castingTick == 0 || 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
|
||||
|
||||
@@ -78,7 +78,7 @@ public abstract class Forfeit {
|
||||
|
||||
public Forfeit(ResourceLocation name){
|
||||
this.name = name;
|
||||
this.sound = WizardrySounds.createSound("forfeit." + name.getPath());
|
||||
this.sound = WizardrySounds.createSound(name.getNamespace(), "forfeit." + name.getPath());
|
||||
}
|
||||
|
||||
public abstract void apply(World world, EntityPlayer player);
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* <b>[Server -> Client]</b> This packet is sent when a bomb entity impacts something. It is used to guarantee that the
|
||||
* client always sees the explosion effect, even in singleplayer where the server may remove the entity before the
|
||||
* client's own simulation can call {@code onImpact()}.
|
||||
*/
|
||||
public class PacketBombExplosion implements IMessageHandler<PacketBombExplosion.Message, IMessage> {
|
||||
|
||||
/** Bomb type constants, matching the order bombs are handled in {@link electroblob.wizardry.CommonProxy}. */
|
||||
public static final int FIREBOMB = 0;
|
||||
public static final int POISON_BOMB = 1;
|
||||
public static final int SMOKE_BOMB = 2;
|
||||
public static final int SPARK_BOMB = 3;
|
||||
|
||||
@Override
|
||||
public IMessage onMessage(Message message, MessageContext ctx){
|
||||
if(ctx.side.isClient()){
|
||||
net.minecraft.client.Minecraft.getMinecraft().addScheduledTask(
|
||||
() -> Wizardry.proxy.handleBombExplosionPacket(message));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static class Message implements IMessage {
|
||||
|
||||
/** One of the bomb type constants defined in {@link PacketBombExplosion}. */
|
||||
public int bombType;
|
||||
public double x, y, z;
|
||||
public float blastMultiplier;
|
||||
/** Entity IDs of secondary targets struck by the spark bomb chain. Empty for other bomb types. */
|
||||
public int[] secondaryTargetIDs;
|
||||
|
||||
// Required no-arg constructor
|
||||
public Message(){}
|
||||
|
||||
public Message(int bombType, double x, double y, double z, float blastMultiplier){
|
||||
this(bombType, x, y, z, blastMultiplier, new int[0]);
|
||||
}
|
||||
|
||||
public Message(int bombType, double x, double y, double z, float blastMultiplier, int[] secondaryTargetIDs){
|
||||
this.bombType = bombType;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.blastMultiplier = blastMultiplier;
|
||||
this.secondaryTargetIDs = secondaryTargetIDs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromBytes(ByteBuf buf){
|
||||
bombType = buf.readInt();
|
||||
x = buf.readDouble();
|
||||
y = buf.readDouble();
|
||||
z = buf.readDouble();
|
||||
blastMultiplier = buf.readFloat();
|
||||
int count = buf.readInt();
|
||||
secondaryTargetIDs = new int[count];
|
||||
for(int i = 0; i < count; i++) secondaryTargetIDs[i] = buf.readInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBytes(ByteBuf buf){
|
||||
buf.writeInt(bombType);
|
||||
buf.writeDouble(x);
|
||||
buf.writeDouble(y);
|
||||
buf.writeDouble(z);
|
||||
buf.writeFloat(blastMultiplier);
|
||||
buf.writeInt(secondaryTargetIDs.length);
|
||||
for(int id : secondaryTargetIDs) buf.writeInt(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,7 @@ public class WizardryPacketHandler {
|
||||
registerMessage(PacketSpellQuickAccess.class, PacketSpellQuickAccess.Message.class);
|
||||
registerMessage(PacketRequestDonationPerks.class, PacketRequestDonationPerks.Message.class);
|
||||
registerMessage(PacketSyncDonationPerks.class, PacketSyncDonationPerks.Message.class);
|
||||
registerMessage(PacketBombExplosion.class, PacketBombExplosion.Message.class);
|
||||
}
|
||||
|
||||
private static int nextPacketId = 0;
|
||||
|
||||
@@ -907,7 +907,7 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
|
||||
* 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));
|
||||
return enabled && (contexts.length == 0 || (arePropertiesInitialised() && properties.isEnabled(contexts)));
|
||||
}
|
||||
|
||||
/** Sets whether the spell is enabled or not. */
|
||||
|
||||
@@ -235,12 +235,11 @@ public class TileEntityImbuementAltar extends TileEntity implements ITickable {
|
||||
*/
|
||||
public static ItemStack getImbuementResult(ItemStack input, Element[] receptacleElements, boolean fullLootGen, World world, EntityPlayer lastUser){
|
||||
|
||||
ItemStack eventResult = ItemStack.EMPTY;
|
||||
ImbuementActivateEvent event = new ImbuementActivateEvent(input, receptacleElements, world, lastUser, ItemStack.EMPTY);
|
||||
|
||||
if (world != null && MinecraftForge.EVENT_BUS.post(new ImbuementActivateEvent(input, receptacleElements, world, lastUser, eventResult))) {
|
||||
// return the stack if something changes the result from an empty stack.
|
||||
//noinspection ConstantConditions
|
||||
if (eventResult != ItemStack.EMPTY) return eventResult;
|
||||
if (world != null && MinecraftForge.EVENT_BUS.post(event)) {
|
||||
// Event was cancelled; return whatever result the handler set (may be empty to suppress all recipes).
|
||||
return event.result;
|
||||
}
|
||||
|
||||
if(input.getItem() instanceof ItemWizardArmour && ((ItemWizardArmour)input.getItem()).element == null){
|
||||
|
||||
@@ -117,6 +117,9 @@ public final class AllyDesignationSystem {
|
||||
// Always return true if the attacker is null - this must be after the target null check!
|
||||
if(attacker == null) return true;
|
||||
|
||||
// Teammates are allies
|
||||
if(attacker.isOnSameTeam(target)) return false;
|
||||
|
||||
// Tests whether the target is the attacker
|
||||
if(target == attacker) return false;
|
||||
|
||||
@@ -220,6 +223,10 @@ public final class AllyDesignationSystem {
|
||||
if(allyOf instanceof EntityPlayer && isOwnerAlly((EntityPlayer)allyOf, pet)) return true;
|
||||
}
|
||||
|
||||
if(possibleAlly.isOnSameTeam(allyOf)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if the possibleAlly is mind controlled by the allyOf entity
|
||||
if(possibleAlly instanceof EntityLiving && possibleAlly.isPotionActive(WizardryPotions.mind_control)){
|
||||
NBTTagCompound entityNBT = possibleAlly.getEntityData();
|
||||
|
||||
@@ -524,6 +524,7 @@ item.ebwizardry\:charm_move_speed.name=Icarus Medallion
|
||||
item.ebwizardry\:charm_move_speed.desc=Move at near-full speed when casting spells
|
||||
item.ebwizardry\:charm_spell_discovery.name=Archivist's Eyeglass
|
||||
item.ebwizardry\:charm_spell_discovery.desc=Spell books found in chests are much more likely to be ones you have not yet discovered
|
||||
item.ebwizardry\:charm_spell_discovery.desc.color=When equipped, you can see the element of a known spell book by the color of its bookmark
|
||||
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
|
||||
@@ -1692,6 +1693,10 @@ 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.spell_book_colors_require_charm=Spell Book Colors Require Archivist's Eyeglass
|
||||
config.ebwizardry.spell_book_colors_require_charm.tooltip=Whether to require the Archivist's Eyeglass charm artifact to see colored spell book bookmarks.
|
||||
config.ebwizardry.spell_book_colors_require_charm.true=Yes - I want to see the colours only if the charm is worn
|
||||
config.ebwizardry.spell_book_colors_require_charm.false=No - I want to see the colours all the time
|
||||
config.ebwizardry.blindness_tweak=Blindness Tweak
|
||||
config.ebwizardry.blindness_tweak.tooltip=Whether to tweak the blindness effect to reduce follow distance when used on non-players. This automatically disables itself in favour of Potion Core's implementation if installed.
|
||||
config.ebwizardry.mob_loot_table_whitelist=Mob Loot Table Whitelist
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "ebwizardry:items/spell_book"
|
||||
},
|
||||
"parent": "ebwizardry:item/spell_book_undiscovered",
|
||||
"overrides": [
|
||||
{
|
||||
"predicate": {
|
||||
"festive": 1
|
||||
},
|
||||
"model": "ebwizardry:item/festive_spell_book"
|
||||
}
|
||||
{"predicate": {"ebwizardry:element": 1}, "model": "ebwizardry:item/spell_book_discovered_magic"},
|
||||
{"predicate": {"ebwizardry:element": 2}, "model": "ebwizardry:item/spell_book_discovered_fire"},
|
||||
{"predicate": {"ebwizardry:element": 3}, "model": "ebwizardry:item/spell_book_discovered_ice"},
|
||||
{"predicate": {"ebwizardry:element": 4}, "model": "ebwizardry:item/spell_book_discovered_lightning"},
|
||||
{"predicate": {"ebwizardry:element": 5}, "model": "ebwizardry:item/spell_book_discovered_necromancy"},
|
||||
{"predicate": {"ebwizardry:element": 6}, "model": "ebwizardry:item/spell_book_discovered_earth"},
|
||||
{"predicate": {"ebwizardry:element": 7}, "model": "ebwizardry:item/spell_book_discovered_sorcery"},
|
||||
{"predicate": {"ebwizardry:element": 8}, "model": "ebwizardry:item/spell_book_discovered_healing"},
|
||||
{"predicate": {"festive": 1}, "model": "ebwizardry:item/festive_spell_book"}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "ebwizardry:items/spell_book",
|
||||
"layer1": "ebwizardry:items/spell_book_overlay"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "ebwizardry:items/spell_book",
|
||||
"layer1": "ebwizardry:items/spell_book_overlay_earth"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "ebwizardry:items/spell_book",
|
||||
"layer1": "ebwizardry:items/spell_book_overlay_fire"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "ebwizardry:items/spell_book",
|
||||
"layer1": "ebwizardry:items/spell_book_overlay_healing"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "ebwizardry:items/spell_book",
|
||||
"layer1": "ebwizardry:items/spell_book_overlay_ice"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "ebwizardry:items/spell_book",
|
||||
"layer1": "ebwizardry:items/spell_book_overlay_lightning"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "ebwizardry:items/spell_book",
|
||||
"layer1": "ebwizardry:items/spell_book_overlay_magic"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "ebwizardry:items/spell_book",
|
||||
"layer1": "ebwizardry:items/spell_book_overlay_necromancy"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "ebwizardry:items/spell_book",
|
||||
"layer1": "ebwizardry:items/spell_book_overlay_sorcery"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"parent": "item/generated",
|
||||
"textures": {
|
||||
"layer0": "ebwizardry:items/spell_book"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 157 B |
|
After Width: | Height: | Size: 145 B |
|
After Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 145 B |
|
After Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 147 B |
|
After Width: | Height: | Size: 147 B |