Compare commits
70 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0328f41564 | |||
| 9ab4684aef | |||
| e64cf9a6af | |||
| f13f220564 | |||
| 311b5750df | |||
| e54aee332d | |||
| e4bf09f15a | |||
| aa166814ea | |||
| d37ab6072f | |||
| ba83cb7985 | |||
| 3052e56d03 | |||
| b682740751 | |||
| 38429cb697 | |||
| dc7b6790b8 | |||
| 7a247df3e1 | |||
| de2087c0e8 | |||
| f5da195605 | |||
| 6cd6411c25 | |||
| 40e77728ad | |||
| d50ff5729f | |||
| 76b4f2f72f | |||
| a608375433 | |||
| c3f8ba245d | |||
| 34b3fe93bb | |||
| 996ec9a7f7 | |||
| 2b38ca9a89 | |||
| 67788a2bd8 | |||
| 58fcaa8af2 | |||
| 24e89c8b8a | |||
| 1293b89905 | |||
| 807fc61541 | |||
| 9741c751b3 | |||
| d3003ae473 | |||
| 9fde24f341 | |||
| 452eb17b5f | |||
| 36963aac30 | |||
| f161cdfe7c | |||
| 455c5a5e07 | |||
| 9852f61d0f | |||
| a2c8cde4c4 | |||
| 497d28eafd | |||
| f3f3377c4d | |||
| 4c81c61644 | |||
| 31a6ab6db0 | |||
| 69f2aedef7 | |||
| e8818a4db5 | |||
| 470a7e82bc | |||
| 6439c233f1 | |||
| c931d42d62 | |||
| 5b497e107a | |||
| 324094f418 | |||
| 9ade6442b2 | |||
| ffea49bc40 | |||
| 2b89a890d0 | |||
| 3a67388ff3 | |||
| 3468bbb073 | |||
| 963178c609 | |||
| cfdb049368 | |||
| 058d83fd00 | |||
| c7ccc37dca | |||
| 74345d0c3b | |||
| 907b94c74f | |||
| 2c6b397be6 | |||
| eddcb2402d | |||
| 0301f3c300 | |||
| 7a8cfb73cd | |||
| c7c6f964bf | |||
| 91df7cfd72 | |||
| 0ed9ee64c4 | |||
| f82d2871d5 |
@@ -7,10 +7,10 @@ assignees: ''
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Please read the [guide for contributing](https://github.com/Electroblob77/Wizardry/blob/1.12.2/guide_for_contributing.md) before posting.
|
Please read the [guide for contributing](https://github.com/Electroblob77/Wizardry/blob/1.12.2/CONTRIBUTING.md) before posting.
|
||||||
|
|
||||||
Minecraft version: 1.12.2 [change as necessary]
|
Minecraft version: 1.12.2 [change as necessary]
|
||||||
Wizardry version: 4.2.2 [change as necessary]
|
Wizardry version: 4.2.8 [change as necessary]
|
||||||
Environment: Singleplayer/LAN game/Server [delete as necessary]
|
Environment: Singleplayer/LAN game/Server [delete as necessary]
|
||||||
|
|
||||||
Issue details: [describe what you were doing when the issue occurred, what went wrong, what you expected to happen, etc.]
|
Issue details: [describe what you were doing when the issue occurred, what went wrong, what you expected to happen, etc.]
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ assignees: ''
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Please read the [guide for contributing](https://github.com/Electroblob77/Wizardry/blob/1.12.2/guide_for_contributing.md) before posting.
|
Please read the [guide for contributing](https://github.com/Electroblob77/Wizardry/blob/1.12.2/CONTRIBUTING.md) before posting.
|
||||||
|
|
||||||
Minecraft versions: [if this suggestion only applies to some versions, list them here]
|
Minecraft versions: [if this suggestion only applies to some versions, list them here]
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ assignees: ''
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Please read the [guide for contributing](https://github.com/Electroblob77/Wizardry/blob/1.12.2/guide_for_contributing.md) before posting.
|
Please read the [guide for contributing](https://github.com/Electroblob77/Wizardry/blob/1.12.2/CONTRIBUTING.md) before posting.
|
||||||
|
|
||||||
Minecraft version: 1.12.2 [change as necessary]
|
Minecraft version: 1.12.2 [change as necessary]
|
||||||
Wizardry version: 4.2.2 [change as necessary]
|
Wizardry version: 4.2.8 [change as necessary]
|
||||||
|
|
||||||
Question details: [explain your question here]
|
Question details: [explain your question here]
|
||||||
|
|
||||||
|
|||||||
+10
-7
@@ -1,7 +1,7 @@
|
|||||||
# Credits
|
# Credits
|
||||||
|
|
||||||
Electroblob's Wizardry
|
Electroblob's Wizardry
|
||||||
Version 4.2.3
|
Version 4.2.8
|
||||||
For Minecraft 1.12.2
|
For Minecraft 1.12.2
|
||||||
|
|
||||||
Designed, coded and textured by Electroblob
|
Designed, coded and textured by Electroblob
|
||||||
@@ -21,15 +21,18 @@ In addition, I'd like to thank the following individuals for their contributions
|
|||||||
- Tora-B
|
- Tora-B
|
||||||
- Avatair
|
- Avatair
|
||||||
- Aeronica
|
- Aeronica
|
||||||
|
- UltraHex
|
||||||
|
- Azim-Palmer
|
||||||
|
- raoulvdberge
|
||||||
|
|
||||||
#### Translations
|
#### Translations
|
||||||
|
|
||||||
- Spanish and Mexican Spanish: MadWrist
|
- Spanish and Mexican Spanish: MadWrist
|
||||||
- Russian: VilagVil, kellixon
|
- Russian: VilagVil, kellixon, bigenergy
|
||||||
- French: Hahdrim
|
- French: Hahdrim
|
||||||
- Brazilian Portuguese: lorrampi
|
- Brazilian Portuguese: lorrampi
|
||||||
- Chinese: ZHENGLOC, dragon-evol
|
- Chinese: ZHENGLOC, dragon-evol
|
||||||
- Korean: shejery, rewi_wire
|
- Korean: shejery, rewi_wire
|
||||||
- Polish: Trozuu
|
- Polish: Trozuu
|
||||||
|
|
||||||
Lightning ray sound effect from OhhWowProductions
|
Lightning ray sound effect from OhhWowProductions
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
Please read the [guide for contributing](https://github.com/Electroblob77/Wizardry/blob/1.12.2/guide_for_contributing.md) before posting.
|
Please read the [guide for contributing](https://github.com/Electroblob77/Wizardry/blob/1.12.2/guide_for_contributing.md) before posting.
|
||||||
|
|
||||||
Minecraft version: 1.12.2 [change as necessary]
|
Minecraft version: 1.12.2 [change as necessary]
|
||||||
Wizardry version: 4.1.4 [change as necessary]
|
Wizardry version: 4.2.8 [change as necessary]
|
||||||
Environment: Singleplayer/LAN game/Server [delete as necessary]
|
Environment: Singleplayer/LAN game/Server [delete as necessary]
|
||||||
|
|
||||||
Issue details: [describe what you were doing when the issue occurred, what went wrong, what you expected to happen, etc.]
|
Issue details: [describe what you were doing when the issue occurred, what went wrong, what you expected to happen, etc.]
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@ 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.
|
//Only edit below this line, the above code adds and enables the necessary things for Forge to be setup.
|
||||||
|
|
||||||
|
|
||||||
version = "4.2.5" // There, it matches semver, happy now?
|
version = "4.2.8" // There, it matches semver, happy now?
|
||||||
group= "electroblob.wizardry"// http://maven.apache.org/guides/mini/guide-naming-conventions.html
|
group= "electroblob.wizardry"// http://maven.apache.org/guides/mini/guide-naming-conventions.html
|
||||||
archivesBaseName = "ElectroblobsWizardry"
|
archivesBaseName = "ElectroblobsWizardry"
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import electroblob.wizardry.spell.Spell;
|
|||||||
import net.minecraft.block.state.IBlockState;
|
import net.minecraft.block.state.IBlockState;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.SoundCategory;
|
import net.minecraft.util.SoundCategory;
|
||||||
@@ -99,9 +100,9 @@ public class CommonProxy {
|
|||||||
return ((ItemSpectralBow)WizardryItems.spectral_bow).getDefaultDurabilityForDisplay(stack);
|
return ((ItemSpectralBow)WizardryItems.spectral_bow).getDefaultDurabilityForDisplay(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Like {@link CommonProxy#addMultiLineDescription(List, String, Style)}, but style defaults to light grey. */
|
/** Like {@link CommonProxy#addMultiLineDescription(List, String, Style, Object...)}, but style defaults to light grey. */
|
||||||
public void addMultiLineDescription(List<String> tooltip, String key){
|
public void addMultiLineDescription(List<String> tooltip, String key, Object... args){
|
||||||
this.addMultiLineDescription(tooltip, key, new Style().setColor(TextFormatting.GRAY));
|
this.addMultiLineDescription(tooltip, key, new Style().setColor(TextFormatting.GRAY), args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -112,7 +113,7 @@ public class CommonProxy {
|
|||||||
* @param key The translation key for the description
|
* @param key The translation key for the description
|
||||||
* @param style A style to apply
|
* @param style A style to apply
|
||||||
*/
|
*/
|
||||||
public void addMultiLineDescription(List<String> tooltip, String key, Style style){}
|
public void addMultiLineDescription(List<String> tooltip, String key, Style style, Object... args){}
|
||||||
|
|
||||||
// SECTION Packet Handlers
|
// SECTION Packet Handlers
|
||||||
// ===============================================================================================================
|
// ===============================================================================================================
|
||||||
@@ -139,8 +140,6 @@ public class CommonProxy {
|
|||||||
|
|
||||||
public void handleAdvancementSyncPacket(PacketSyncAdvancements.Message message){}
|
public void handleAdvancementSyncPacket(PacketSyncAdvancements.Message message){}
|
||||||
|
|
||||||
public void handleEndSlowTimePacket(PacketEndSlowTime.Message message){}
|
|
||||||
|
|
||||||
public void handleResurrectionPacket(PacketResurrection.Message message){}
|
public void handleResurrectionPacket(PacketResurrection.Message message){}
|
||||||
|
|
||||||
public void handlePossessionPacket(PacketPossession.Message message){}
|
public void handlePossessionPacket(PacketPossession.Message message){}
|
||||||
@@ -238,6 +237,9 @@ public class CommonProxy {
|
|||||||
+ "of sound events, but the given array contained less than 3 sound events!");
|
+ "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);
|
playSpellSoundLoop(world, x, y, z, spell, sounds[0], sounds[1], sounds[2], category, volume, pitch, duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Starts the first-person blink overlay effect for the specified player. */
|
||||||
|
public void playBlinkEffect(EntityPlayer player){}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the client side world using Minecraft.getMinecraft().world. <b>Only to be called client side!</b> Returns
|
* Gets the client side world using Minecraft.getMinecraft().world. <b>Only to be called client side!</b> Returns
|
||||||
|
|||||||
@@ -169,6 +169,8 @@ public final class Settings {
|
|||||||
/** <b>[Server-only]</b> Whether to replace Minecraft's distance-based fall damage calculation with an equivalent,
|
/** <b>[Server-only]</b> Whether to replace Minecraft's distance-based fall damage calculation with an equivalent,
|
||||||
* velocity-based one. */
|
* velocity-based one. */
|
||||||
public boolean replaceVanillaFallDamage = true;
|
public boolean replaceVanillaFallDamage = true;
|
||||||
|
/** <b>[Server-only]</b> Whether using bonemeal on grass blocks has a chance to grow crystal flowers. */
|
||||||
|
public boolean bonemealGrowsCrystalFlowers = true;
|
||||||
/**
|
/**
|
||||||
* <b>[Server-only]</b> List of registry names of entities which summoned creatures are allowed to attack, in addition
|
* <b>[Server-only]</b> List of registry names of entities which summoned creatures are allowed to attack, in addition
|
||||||
* to the defaults.
|
* to the defaults.
|
||||||
@@ -431,7 +433,7 @@ public final class Settings {
|
|||||||
|
|
||||||
Property property;
|
Property property;
|
||||||
|
|
||||||
for(Spell spell : Spell.getSpells(Spell.allSpells)){
|
for(Spell spell : Spell.getAllSpells()){
|
||||||
property = config.get(SPELLS_CATEGORY, spell.getRegistryName().toString(), true,
|
property = config.get(SPELLS_CATEGORY, spell.getRegistryName().toString(), true,
|
||||||
I18n.translateToLocal("spell." + spell.getUnlocalisedName() + ".desc"));
|
I18n.translateToLocal("spell." + spell.getUnlocalisedName() + ".desc"));
|
||||||
// Uses the same config key as the spell name, because - well, that's what it's called!
|
// Uses the same config key as the spell name, because - well, that's what it's called!
|
||||||
@@ -542,6 +544,13 @@ public final class Settings {
|
|||||||
slowTimeAffectsPlayers = property.getBoolean();
|
slowTimeAffectsPlayers = property.getBoolean();
|
||||||
propOrder.add(property.getName());
|
propOrder.add(property.getName());
|
||||||
|
|
||||||
|
property = config.get(GAMEPLAY_CATEGORY, "bonemealGrowsCrystalFlowers", true,
|
||||||
|
"Whether using bonemeal on grass blocks has a chance to grow crystal flowers.");
|
||||||
|
property.setLanguageKey("config." + Wizardry.MODID + ".bonemeal_grows_crystal_flowers");
|
||||||
|
Wizardry.proxy.setToNamedBooleanEntry(property);
|
||||||
|
bonemealGrowsCrystalFlowers = 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 = 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.setLanguageKey("config." + Wizardry.MODID + ".mob_loot_table_whitelist");
|
||||||
property.setRequiresMcRestart(true);
|
property.setRequiresMcRestart(true);
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import net.minecraftforge.fml.common.registry.GameRegistry;
|
|||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.Calendar;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <i>"Electroblob's Wizardry adds an RPG-like system of spells to Minecraft, with the aim of being as playable as
|
* <i>"Electroblob's Wizardry adds an RPG-like system of spells to Minecraft, with the aim of being as playable as
|
||||||
@@ -63,7 +64,7 @@ public class Wizardry {
|
|||||||
* 1.x.x represents Minecraft 1.7.x versions, 2.x.x represents Minecraft 1.10.x versions, 3.x.x represents Minecraft
|
* 1.x.x represents Minecraft 1.7.x versions, 2.x.x represents Minecraft 1.10.x versions, 3.x.x represents Minecraft
|
||||||
* 1.11.x versions, and so on.
|
* 1.11.x versions, and so on.
|
||||||
*/
|
*/
|
||||||
public static final String VERSION = "4.2.5";
|
public static final String VERSION = "4.2.8";
|
||||||
|
|
||||||
// IDEA: Triggering of inbuilt Forge events in relevant places?
|
// IDEA: Triggering of inbuilt Forge events in relevant places?
|
||||||
// IDEA: Abstract the vanilla particles behind the particle builder
|
// IDEA: Abstract the vanilla particles behind the particle builder
|
||||||
@@ -88,6 +89,8 @@ public class Wizardry {
|
|||||||
* this folder contains the main config file and the global spell properties folder, if used. */
|
* this folder contains the main config file and the global spell properties folder, if used. */
|
||||||
public static File configDirectory;
|
public static File configDirectory;
|
||||||
|
|
||||||
|
public static boolean tisTheSeason;
|
||||||
|
|
||||||
// The instance of wizardry that Forge uses.
|
// The instance of wizardry that Forge uses.
|
||||||
@Instance(Wizardry.MODID)
|
@Instance(Wizardry.MODID)
|
||||||
public static Wizardry instance;
|
public static Wizardry instance;
|
||||||
@@ -106,6 +109,10 @@ public class Wizardry {
|
|||||||
configDirectory = new File(event.getModConfigurationDirectory(), Wizardry.MODID);
|
configDirectory = new File(event.getModConfigurationDirectory(), Wizardry.MODID);
|
||||||
settings.initConfig(event);
|
settings.initConfig(event);
|
||||||
|
|
||||||
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
tisTheSeason = calendar.get(Calendar.MONTH) + 1 == 12 && calendar.get(Calendar.DAY_OF_MONTH) >= 24
|
||||||
|
&& calendar.get(Calendar.DAY_OF_MONTH) <= 26;
|
||||||
|
|
||||||
// Capabilities
|
// Capabilities
|
||||||
WizardData.register();
|
WizardData.register();
|
||||||
DispenserCastingData.register();
|
DispenserCastingData.register();
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ import net.minecraft.util.ResourceLocation;
|
|||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.util.text.TextComponentTranslation;
|
import net.minecraft.util.text.TextComponentTranslation;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.WorldServer;
|
||||||
|
import net.minecraft.world.storage.loot.LootContext;
|
||||||
|
import net.minecraft.world.storage.loot.LootTable;
|
||||||
import net.minecraftforge.common.MinecraftForge;
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
import net.minecraftforge.common.util.FakePlayer;
|
import net.minecraftforge.common.util.FakePlayer;
|
||||||
import net.minecraftforge.event.entity.PlaySoundAtEntityEvent;
|
import net.minecraftforge.event.entity.PlaySoundAtEntityEvent;
|
||||||
@@ -46,6 +49,7 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
|||||||
import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerLoggedInEvent;
|
import net.minecraftforge.fml.common.gameevent.PlayerEvent.PlayerLoggedInEvent;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* General-purpose event handler for things that don't fit anywhere else or groups of related behaviours that are better
|
* General-purpose event handler for things that don't fit anywhere else or groups of related behaviours that are better
|
||||||
@@ -343,18 +347,21 @@ public final class WizardryEventHandler {
|
|||||||
|
|
||||||
Spell spell = ((ISpellCaster)event.getEntity()).getContinuousSpell();
|
Spell spell = ((ISpellCaster)event.getEntity()).getContinuousSpell();
|
||||||
SpellModifiers modifiers = ((ISpellCaster)event.getEntity()).getModifiers();
|
SpellModifiers modifiers = ((ISpellCaster)event.getEntity()).getModifiers();
|
||||||
|
int count = ((ISpellCaster)event.getEntity()).getSpellCounter();
|
||||||
|
|
||||||
if(spell != null && spell != Spells.none){ // IntelliJ is wrong, do NOT remove the null check!
|
if(spell != null && spell != Spells.none){ // IntelliJ is wrong, do NOT remove the null check!
|
||||||
|
|
||||||
if(!MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Tick(SpellCastEvent.Source.NPC, spell, event.getEntityLiving(),
|
if(!MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Tick(SpellCastEvent.Source.NPC, spell, event.getEntityLiving(),
|
||||||
modifiers, 0))){
|
modifiers, count))){
|
||||||
|
|
||||||
spell.cast(event.getEntity().world, (EntityLiving)event.getEntity(), EnumHand.MAIN_HAND, 0,
|
spell.cast(event.getEntity().world, (EntityLiving)event.getEntity(), EnumHand.MAIN_HAND, count,
|
||||||
// TODO: This implementation of modifiers relies on them being accessible client-side.
|
// 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
|
// Right now that doesn't matter because NPCs don't use modifiers, but they might in future
|
||||||
((EntityLiving)event.getEntity()).getAttackTarget(), modifiers);
|
((EntityLiving)event.getEntity()).getAttackTarget(), modifiers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
((ISpellCaster)event.getEntity()).setSpellCounter(count + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -366,6 +373,22 @@ public final class WizardryEventHandler {
|
|||||||
|
|
||||||
EntityPlayer player = (EntityPlayer)event.getSource().getTrueSource();
|
EntityPlayer player = (EntityPlayer)event.getSource().getTrueSource();
|
||||||
|
|
||||||
|
// Compatibility with "Lycanites Mobs" -it uses custom loot drop logic which can't be hooked, given the
|
||||||
|
// number of mobs that spawn as Lycanites when this mod is active it would massively nerf the wizard drops
|
||||||
|
// if we didn't handle this
|
||||||
|
if(event.getEntity().getClass().getCanonicalName().contains("lycanitesmobs"))
|
||||||
|
{
|
||||||
|
WorldServer world = (WorldServer)event.getEntity().getEntityWorld();
|
||||||
|
LootTable table = world.getLootTableManager().getLootTableFromLocation(new ResourceLocation(Wizardry.MODID, "entities/mob_additions"));
|
||||||
|
|
||||||
|
LootContext ctx = new LootContext.Builder(world).withPlayer(player).build();
|
||||||
|
List<ItemStack> stacks = table.generateLootForPools(world.rand, ctx);
|
||||||
|
|
||||||
|
for(ItemStack stack : stacks) {
|
||||||
|
event.getEntity().entityDropItem(stack, 0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(ItemStack stack : WizardryUtilities.getPrioritisedHotbarAndOffhand(player)){
|
for(ItemStack stack : WizardryUtilities.getPrioritisedHotbarAndOffhand(player)){
|
||||||
|
|
||||||
if(stack.getItem() instanceof IManaStoringItem && !((IManaStoringItem)stack.getItem()).isManaFull(stack)
|
if(stack.getItem() instanceof IManaStoringItem && !((IManaStoringItem)stack.getItem()).isManaFull(stack)
|
||||||
@@ -444,7 +467,8 @@ public final class WizardryEventHandler {
|
|||||||
// Wizardry.logger.info("Replaced fall distance {} with effective distance {} based on entity velocity", event.getDistance(), y);
|
// Wizardry.logger.info("Replaced fall distance {} with effective distance {} based on entity velocity", event.getDistance(), y);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
event.setDistance((float)y);
|
// Don't let it increase fall damage beyond vanilla values
|
||||||
|
if(y < event.getDistance()) event.setDistance((float)y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package electroblob.wizardry.block;
|
package electroblob.wizardry.block;
|
||||||
|
|
||||||
|
import electroblob.wizardry.Wizardry;
|
||||||
import electroblob.wizardry.registry.WizardryBlocks;
|
import electroblob.wizardry.registry.WizardryBlocks;
|
||||||
import electroblob.wizardry.util.ParticleBuilder;
|
import electroblob.wizardry.util.ParticleBuilder;
|
||||||
import electroblob.wizardry.util.ParticleBuilder.Type;
|
import electroblob.wizardry.util.ParticleBuilder.Type;
|
||||||
@@ -56,7 +57,7 @@ public class BlockCrystalFlower extends BlockBush {
|
|||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onBonemealEvent(BonemealEvent event){
|
public static void onBonemealEvent(BonemealEvent event){
|
||||||
// Grows crystal flowers when bonemeal is used on grass
|
// Grows crystal flowers when bonemeal is used on grass
|
||||||
if(event.getBlock().getBlock() == Blocks.GRASS){
|
if(Wizardry.settings.bonemealGrowsCrystalFlowers && event.getBlock().getBlock() == Blocks.GRASS){
|
||||||
|
|
||||||
BlockPos pos = event.getPos().add(event.getWorld().rand.nextInt(8) - event.getWorld().rand.nextInt(8),
|
BlockPos pos = event.getPos().add(event.getWorld().rand.nextInt(8) - event.getWorld().rand.nextInt(8),
|
||||||
event.getWorld().rand.nextInt(4) - event.getWorld().rand.nextInt(4),
|
event.getWorld().rand.nextInt(4) - event.getWorld().rand.nextInt(4),
|
||||||
|
|||||||
@@ -141,7 +141,8 @@ public class BlockTransportationStone extends Block {
|
|||||||
if(locations.isEmpty()) locations.add(here);
|
if(locations.isEmpty()) locations.add(here);
|
||||||
else{
|
else{
|
||||||
locations.remove(here); // Prevents duplicates
|
locations.remove(here); // Prevents duplicates
|
||||||
locations.set(Math.max(locations.size() - 1, 0), here);
|
if(locations.isEmpty()) locations.add(here);
|
||||||
|
else locations.set(Math.max(locations.size() - 1, 0), here);
|
||||||
}
|
}
|
||||||
if(!world.isRemote) player.sendStatusMessage(new TextComponentTranslation("tile." + Wizardry.MODID + ":transportation_stone.confirm", Spells.transportation.getNameForTranslationFormatted()), true);
|
if(!world.isRemote) player.sendStatusMessage(new TextComponentTranslation("tile." + Wizardry.MODID + ":transportation_stone.confirm", Spells.transportation.getNameForTranslationFormatted()), true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ public class ClientProxy extends CommonProxy {
|
|||||||
// Armour Model
|
// Armour Model
|
||||||
public static final ModelBiped WIZARD_ARMOUR_MODEL = new ModelWizardArmour(0.75f);
|
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)}). */
|
/** The wrap width for standard multi-line descriptions (see {@link ClientProxy#addMultiLineDescription(List, String, Style, Object...)}). */
|
||||||
private static final int TOOLTIP_WRAP_WIDTH = 140;
|
private static final int TOOLTIP_WRAP_WIDTH = 140;
|
||||||
|
|
||||||
// SECTION Registry
|
// SECTION Registry
|
||||||
@@ -190,6 +190,11 @@ public class ClientProxy extends CommonProxy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playBlinkEffect(EntityPlayer player){
|
||||||
|
if(Minecraft.getMinecraft().player == player) WizardryClientEventHandler.playBlinkEffect();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getSpellHUDSkins(){
|
public Set<String> getSpellHUDSkins(){
|
||||||
return GuiSpellDisplay.getSkinKeys();
|
return GuiSpellDisplay.getSkinKeys();
|
||||||
@@ -282,8 +287,8 @@ public class ClientProxy extends CommonProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addMultiLineDescription(List<String> tooltip, String key, Style style){
|
public void addMultiLineDescription(List<String> tooltip, String key, Style style, Object... args){
|
||||||
String description = style.getFormattingCode() + I18n.format(key);
|
String description = style.getFormattingCode() + I18n.format(key, args);
|
||||||
tooltip.addAll(Minecraft.getMinecraft().fontRenderer.listFormattedStringToWidth(description, TOOLTIP_WRAP_WIDTH));
|
tooltip.addAll(Minecraft.getMinecraft().fontRenderer.listFormattedStringToWidth(description, TOOLTIP_WRAP_WIDTH));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -429,6 +434,7 @@ public class ClientProxy extends CommonProxy {
|
|||||||
if(caster instanceof ISpellCaster){
|
if(caster instanceof ISpellCaster){
|
||||||
if(spell.isContinuous || spell instanceof None){
|
if(spell.isContinuous || spell instanceof None){
|
||||||
((ISpellCaster)caster).setContinuousSpell(spell);
|
((ISpellCaster)caster).setContinuousSpell(spell);
|
||||||
|
((ISpellCaster)caster).setSpellCounter(spell instanceof None ? 0 : 1);
|
||||||
((EntityLiving)caster).setAttackTarget((EntityLivingBase)target);
|
((EntityLiving)caster).setAttackTarget((EntityLivingBase)target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -542,7 +548,7 @@ public class ClientProxy extends CommonProxy {
|
|||||||
data.randomNames = new HashMap<>();
|
data.randomNames = new HashMap<>();
|
||||||
data.randomDescriptions = new HashMap<>();
|
data.randomDescriptions = new HashMap<>();
|
||||||
|
|
||||||
for(Spell spell : Spell.getSpells(Spell.allSpells)){
|
for(Spell spell : Spell.getAllSpells()){
|
||||||
// -1 because the none spell isn't included
|
// -1 because the none spell isn't included
|
||||||
// This is a case where we must use the network ID, not the metadata
|
// 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.randomNames.put(spell, message.names.get(spell.networkID() - 1));
|
||||||
@@ -569,13 +575,6 @@ public class ClientProxy extends CommonProxy {
|
|||||||
GuiWizardHandbook.updateUnlockStatus(message.showToasts, message.completedAdvancements);
|
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
|
@Override
|
||||||
public void handleResurrectionPacket(PacketResurrection.Message message){
|
public void handleResurrectionPacket(PacketResurrection.Message message){
|
||||||
Entity entity = Minecraft.getMinecraft().world.getEntityByID(message.playerID);
|
Entity entity = Minecraft.getMinecraft().world.getEntityByID(message.playerID);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import electroblob.wizardry.data.WizardData;
|
|||||||
import electroblob.wizardry.item.ISpellCastingItem;
|
import electroblob.wizardry.item.ISpellCastingItem;
|
||||||
import electroblob.wizardry.item.ItemArtefact;
|
import electroblob.wizardry.item.ItemArtefact;
|
||||||
import electroblob.wizardry.item.ItemSpectralBow;
|
import electroblob.wizardry.item.ItemSpectralBow;
|
||||||
|
import electroblob.wizardry.potion.PotionSlowTime;
|
||||||
import electroblob.wizardry.registry.Spells;
|
import electroblob.wizardry.registry.Spells;
|
||||||
import electroblob.wizardry.registry.WizardryItems;
|
import electroblob.wizardry.registry.WizardryItems;
|
||||||
import electroblob.wizardry.registry.WizardryPotions;
|
import electroblob.wizardry.registry.WizardryPotions;
|
||||||
@@ -23,11 +24,8 @@ import net.minecraft.client.renderer.OpenGlHelper;
|
|||||||
import net.minecraft.client.renderer.Tessellator;
|
import net.minecraft.client.renderer.Tessellator;
|
||||||
import net.minecraft.client.renderer.entity.RenderManager;
|
import net.minecraft.client.renderer.entity.RenderManager;
|
||||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||||
import net.minecraft.client.settings.KeyBinding;
|
|
||||||
import net.minecraft.entity.EntityLiving;
|
import net.minecraft.entity.EntityLiving;
|
||||||
import net.minecraft.entity.EntityLivingBase;
|
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.item.EntityArmorStand;
|
||||||
import net.minecraft.inventory.Slot;
|
import net.minecraft.inventory.Slot;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
@@ -35,18 +33,17 @@ import net.minecraft.tileentity.TileEntity;
|
|||||||
import net.minecraft.tileentity.TileEntityDispenser;
|
import net.minecraft.tileentity.TileEntityDispenser;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.math.RayTraceResult;
|
import net.minecraft.util.math.RayTraceResult;
|
||||||
import net.minecraft.util.math.Vec3d;
|
|
||||||
import net.minecraft.village.MerchantRecipe;
|
import net.minecraft.village.MerchantRecipe;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraftforge.client.event.*;
|
import net.minecraftforge.client.event.*;
|
||||||
import net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
|
|
||||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||||
import net.minecraftforge.fml.relauncher.Side;
|
import net.minecraftforge.fml.relauncher.Side;
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event handler responsible for client-side only events, mostly rendering.
|
* Event handler responsible for client-side only events, mostly rendering.
|
||||||
@@ -71,12 +68,6 @@ public final class WizardryClientEventHandler {
|
|||||||
private static int blinkEffectTimer;
|
private static int blinkEffectTimer;
|
||||||
/** The number of ticks the blink effect lasts for. */
|
/** The number of ticks the blink effect lasts for. */
|
||||||
private static final int BLINK_EFFECT_DURATION = 8;
|
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. */
|
/** Starts the first person blink overlay effect. */
|
||||||
public static void playBlinkEffect(){
|
public static void playBlinkEffect(){
|
||||||
@@ -151,7 +142,10 @@ public final class WizardryClientEventHandler {
|
|||||||
|
|
||||||
if(world == null) return;
|
if(world == null) return;
|
||||||
|
|
||||||
for(TileEntity tileentity : world.loadedTileEntityList){
|
// Somehow this was throwing a CME, I have no idea why so I'm just going to cheat and copy the list
|
||||||
|
List<TileEntity> tileEntities = new ArrayList<>(world.loadedTileEntityList);
|
||||||
|
|
||||||
|
for(TileEntity tileentity : tileEntities){
|
||||||
if(tileentity instanceof TileEntityDispenser){
|
if(tileentity instanceof TileEntityDispenser){
|
||||||
if(DispenserCastingData.get((TileEntityDispenser)tileentity) != null){
|
if(DispenserCastingData.get((TileEntityDispenser)tileentity) != null){
|
||||||
DispenserCastingData.get((TileEntityDispenser)tileentity).update();
|
DispenserCastingData.get((TileEntityDispenser)tileentity).update();
|
||||||
@@ -160,6 +154,7 @@ public final class WizardryClientEventHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SpellEmitterData.update(world);
|
SpellEmitterData.update(world);
|
||||||
|
PotionSlowTime.cleanUpEntities(world);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ import net.minecraft.inventory.Slot;
|
|||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.util.math.MathHelper;
|
|
||||||
import net.minecraft.util.text.TextFormatting;
|
import net.minecraft.util.text.TextFormatting;
|
||||||
import net.minecraftforge.client.event.TextureStitchEvent;
|
import net.minecraftforge.client.event.TextureStitchEvent;
|
||||||
import net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package electroblob.wizardry.client.model;
|
package electroblob.wizardry.client.model;
|
||||||
|
|
||||||
|
import electroblob.wizardry.Wizardry;
|
||||||
import electroblob.wizardry.block.BlockStatue;
|
import electroblob.wizardry.block.BlockStatue;
|
||||||
import net.minecraft.client.model.ModelRenderer;
|
import net.minecraft.client.model.ModelRenderer;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
@@ -13,6 +14,7 @@ public class ModelWizardArmour extends ModelArmourFixer {
|
|||||||
ModelRenderer hatSegment4;
|
ModelRenderer hatSegment4;
|
||||||
ModelRenderer hatSegment5;
|
ModelRenderer hatSegment5;
|
||||||
ModelRenderer hatSegment6;
|
ModelRenderer hatSegment6;
|
||||||
|
ModelRenderer hatBobble;
|
||||||
ModelRenderer robe;
|
ModelRenderer robe;
|
||||||
|
|
||||||
public ModelWizardArmour(float delta){
|
public ModelWizardArmour(float delta){
|
||||||
@@ -75,6 +77,13 @@ public class ModelWizardArmour extends ModelArmourFixer {
|
|||||||
hatSegment6.mirror = true;
|
hatSegment6.mirror = true;
|
||||||
setRotation(hatSegment6, -0.5585054F, 0F, 0F);
|
setRotation(hatSegment6, -0.5585054F, 0F, 0F);
|
||||||
|
|
||||||
|
hatBobble = new ModelRenderer(this, 52, 47);
|
||||||
|
hatBobble.addBox(0F, 0F, 0F, 3, 3, 3);
|
||||||
|
hatBobble.setRotationPoint(-1.5F, -15.1F, 4F);
|
||||||
|
hatBobble.setTextureSize(64, 64);
|
||||||
|
hatBobble.mirror = true;
|
||||||
|
setRotation(hatBobble, -0.65F, 0F, 0F);
|
||||||
|
|
||||||
bipedBody = new ModelRenderer(this, 16, 16);
|
bipedBody = new ModelRenderer(this, 16, 16);
|
||||||
bipedBody.addBox(-4F, 0F, -2F, 8, 11, 4, delta);
|
bipedBody.addBox(-4F, 0F, -2F, 8, 11, 4, delta);
|
||||||
bipedBody.setRotationPoint(0F, 0F, 0F);
|
bipedBody.setRotationPoint(0F, 0F, 0F);
|
||||||
@@ -97,6 +106,7 @@ public class ModelWizardArmour extends ModelArmourFixer {
|
|||||||
bipedHead.addChild(hatSegment4);
|
bipedHead.addChild(hatSegment4);
|
||||||
bipedHead.addChild(hatSegment5);
|
bipedHead.addChild(hatSegment5);
|
||||||
bipedHead.addChild(hatSegment6);
|
bipedHead.addChild(hatSegment6);
|
||||||
|
bipedHead.addChild(hatBobble);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5){
|
public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5){
|
||||||
@@ -129,6 +139,8 @@ public class ModelWizardArmour extends ModelArmourFixer {
|
|||||||
this.robe.rotateAngleX = (this.bipedLeftLeg.rotateAngleX + this.bipedRightLeg.rotateAngleX) / 2f;
|
this.robe.rotateAngleX = (this.bipedLeftLeg.rotateAngleX + this.bipedRightLeg.rotateAngleX) / 2f;
|
||||||
this.robe.rotateAngleY = this.bipedBody.rotateAngleY;
|
this.robe.rotateAngleY = this.bipedBody.rotateAngleY;
|
||||||
this.robe.rotateAngleZ = (this.bipedLeftLeg.rotateAngleZ + this.bipedRightLeg.rotateAngleZ) / 2f;
|
this.robe.rotateAngleZ = (this.bipedLeftLeg.rotateAngleZ + this.bipedRightLeg.rotateAngleZ) / 2f;
|
||||||
|
|
||||||
|
this.hatBobble.showModel = Wizardry.tisTheSeason;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,10 +67,10 @@ public final class WizardryModels {
|
|||||||
|
|
||||||
registerMultiTexturedModel((ItemCrystal)WizardryItems.magic_crystal);
|
registerMultiTexturedModel((ItemCrystal)WizardryItems.magic_crystal);
|
||||||
|
|
||||||
registerItemModel(WizardryItems.magic_wand);
|
registerWandModel(WizardryItems.magic_wand);
|
||||||
registerItemModel(WizardryItems.apprentice_wand);
|
registerWandModel(WizardryItems.apprentice_wand);
|
||||||
registerItemModel(WizardryItems.advanced_wand);
|
registerWandModel(WizardryItems.advanced_wand);
|
||||||
registerItemModel(WizardryItems.master_wand);
|
registerWandModel(WizardryItems.master_wand);
|
||||||
|
|
||||||
registerItemModel(WizardryItems.spell_book);
|
registerItemModel(WizardryItems.spell_book);
|
||||||
// Wildcard registered for wizard trades.
|
// Wildcard registered for wizard trades.
|
||||||
@@ -78,37 +78,37 @@ public final class WizardryModels {
|
|||||||
registerItemModel(WizardryItems.arcane_tome);
|
registerItemModel(WizardryItems.arcane_tome);
|
||||||
registerItemModel(WizardryItems.wizard_handbook);
|
registerItemModel(WizardryItems.wizard_handbook);
|
||||||
|
|
||||||
registerItemModel(WizardryItems.novice_fire_wand);
|
registerWandModel(WizardryItems.novice_fire_wand);
|
||||||
registerItemModel(WizardryItems.novice_ice_wand);
|
registerWandModel(WizardryItems.novice_ice_wand);
|
||||||
registerItemModel(WizardryItems.novice_lightning_wand);
|
registerWandModel(WizardryItems.novice_lightning_wand);
|
||||||
registerItemModel(WizardryItems.novice_necromancy_wand);
|
registerWandModel(WizardryItems.novice_necromancy_wand);
|
||||||
registerItemModel(WizardryItems.novice_earth_wand);
|
registerWandModel(WizardryItems.novice_earth_wand);
|
||||||
registerItemModel(WizardryItems.novice_sorcery_wand);
|
registerWandModel(WizardryItems.novice_sorcery_wand);
|
||||||
registerItemModel(WizardryItems.novice_healing_wand);
|
registerWandModel(WizardryItems.novice_healing_wand);
|
||||||
|
|
||||||
registerItemModel(WizardryItems.apprentice_fire_wand);
|
registerWandModel(WizardryItems.apprentice_fire_wand);
|
||||||
registerItemModel(WizardryItems.apprentice_ice_wand);
|
registerWandModel(WizardryItems.apprentice_ice_wand);
|
||||||
registerItemModel(WizardryItems.apprentice_lightning_wand);
|
registerWandModel(WizardryItems.apprentice_lightning_wand);
|
||||||
registerItemModel(WizardryItems.apprentice_necromancy_wand);
|
registerWandModel(WizardryItems.apprentice_necromancy_wand);
|
||||||
registerItemModel(WizardryItems.apprentice_earth_wand);
|
registerWandModel(WizardryItems.apprentice_earth_wand);
|
||||||
registerItemModel(WizardryItems.apprentice_sorcery_wand);
|
registerWandModel(WizardryItems.apprentice_sorcery_wand);
|
||||||
registerItemModel(WizardryItems.apprentice_healing_wand);
|
registerWandModel(WizardryItems.apprentice_healing_wand);
|
||||||
|
|
||||||
registerItemModel(WizardryItems.advanced_fire_wand);
|
registerWandModel(WizardryItems.advanced_fire_wand);
|
||||||
registerItemModel(WizardryItems.advanced_ice_wand);
|
registerWandModel(WizardryItems.advanced_ice_wand);
|
||||||
registerItemModel(WizardryItems.advanced_lightning_wand);
|
registerWandModel(WizardryItems.advanced_lightning_wand);
|
||||||
registerItemModel(WizardryItems.advanced_necromancy_wand);
|
registerWandModel(WizardryItems.advanced_necromancy_wand);
|
||||||
registerItemModel(WizardryItems.advanced_earth_wand);
|
registerWandModel(WizardryItems.advanced_earth_wand);
|
||||||
registerItemModel(WizardryItems.advanced_sorcery_wand);
|
registerWandModel(WizardryItems.advanced_sorcery_wand);
|
||||||
registerItemModel(WizardryItems.advanced_healing_wand);
|
registerWandModel(WizardryItems.advanced_healing_wand);
|
||||||
|
|
||||||
registerItemModel(WizardryItems.master_fire_wand);
|
registerWandModel(WizardryItems.master_fire_wand);
|
||||||
registerItemModel(WizardryItems.master_ice_wand);
|
registerWandModel(WizardryItems.master_ice_wand);
|
||||||
registerItemModel(WizardryItems.master_lightning_wand);
|
registerWandModel(WizardryItems.master_lightning_wand);
|
||||||
registerItemModel(WizardryItems.master_necromancy_wand);
|
registerWandModel(WizardryItems.master_necromancy_wand);
|
||||||
registerItemModel(WizardryItems.master_earth_wand);
|
registerWandModel(WizardryItems.master_earth_wand);
|
||||||
registerItemModel(WizardryItems.master_sorcery_wand);
|
registerWandModel(WizardryItems.master_sorcery_wand);
|
||||||
registerItemModel(WizardryItems.master_healing_wand);
|
registerWandModel(WizardryItems.master_healing_wand);
|
||||||
|
|
||||||
registerItemModel(WizardryItems.spectral_sword);
|
registerItemModel(WizardryItems.spectral_sword);
|
||||||
registerItemModel(WizardryItems.spectral_pickaxe);
|
registerItemModel(WizardryItems.spectral_pickaxe);
|
||||||
@@ -303,6 +303,23 @@ public final class WizardryModels {
|
|||||||
// Assigns the model for all metadata values
|
// Assigns the model for all metadata values
|
||||||
ModelLoader.setCustomMeshDefinition(item, s -> new ModelResourceLocation(item.getRegistryName(), "inventory"));
|
ModelLoader.setCustomMeshDefinition(item, s -> new ModelResourceLocation(item.getRegistryName(), "inventory"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a wand model, using the item's registry name as the model name (this convention makes it easier to
|
||||||
|
* keep track of everything).
|
||||||
|
*/
|
||||||
|
private static void registerWandModel(Item item){
|
||||||
|
|
||||||
|
if(Wizardry.tisTheSeason){
|
||||||
|
// Changing the last parameter from null to "inventory" fixed the item/block model weirdness. No idea why!
|
||||||
|
ModelBakery.registerItemVariants(item, new ModelResourceLocation("ebwizardry:festive_wand", "inventory"));
|
||||||
|
// Assigns the model for all metadata values
|
||||||
|
ModelLoader.setCustomMeshDefinition(item, s -> new ModelResourceLocation("ebwizardry:festive_wand", "inventory"));
|
||||||
|
}else{
|
||||||
|
registerItemModel(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers an item model, using the itemstack-sensitive {@link IMultiTexturedItem#getModelName(ItemStack)} as the
|
* Registers an item model, using the itemstack-sensitive {@link IMultiTexturedItem#getModelName(ItemStack)} as the
|
||||||
|
|||||||
@@ -525,30 +525,42 @@ public abstract class ParticleWizardry extends Particle {
|
|||||||
|
|
||||||
|
|
||||||
// =============================================== Helper Methods ===============================================
|
// =============================================== Helper Methods ===============================================
|
||||||
|
|
||||||
|
/** Internal overload for {@link ParticleWizardry#generateTextures(String, String, int)} which uses wizardry's mod
|
||||||
|
* ID automatically. */
|
||||||
|
public static ResourceLocation[] generateTextures(String stem, int n){
|
||||||
|
return generateTextures(Wizardry.MODID, stem, n);
|
||||||
|
}
|
||||||
|
|
||||||
/** Static helper method that generates an array of n ResourceLocations using the particle file naming convention,
|
/** Static helper method that generates an array of n ResourceLocations using the particle file naming convention,
|
||||||
* which is the given stem plus an underscore plus the integer index. */
|
* which is the given stem plus an underscore plus the integer index. */
|
||||||
public static ResourceLocation[] generateTextures(String stem, int n){
|
public static ResourceLocation[] generateTextures(String modID, String stem, int n){
|
||||||
|
|
||||||
ResourceLocation[] textures = new ResourceLocation[n];
|
ResourceLocation[] textures = new ResourceLocation[n];
|
||||||
|
|
||||||
for(int i=0; i<n; i++){
|
for(int i=0; i<n; i++){
|
||||||
textures[i] = new ResourceLocation(Wizardry.MODID, "particle/" + stem + "_" + i);
|
textures[i] = new ResourceLocation(modID, "particle/" + stem + "_" + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
return textures;
|
return textures;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Internal overload for {@link ParticleWizardry#generateTextures(String, String, int, int)} which uses wizardry's
|
||||||
|
* mod ID automatically. */
|
||||||
|
public static ResourceLocation[][] generateTextures(String stem, int m, int n){
|
||||||
|
return generateTextures(Wizardry.MODID, stem, m, n);
|
||||||
|
}
|
||||||
|
|
||||||
/** Static helper method that generates a 2D m x n array of ResourceLocations using the particle file naming
|
/** Static helper method that generates a 2D m x n array of ResourceLocations using the particle file naming
|
||||||
* convention, which is the given stem plus an underscore plus the first index, plus an underscore plus the second
|
* convention, which is the given stem plus an underscore plus the first index, plus an underscore plus the second
|
||||||
* index. Useful for animated particles that also pick a random animation strip. */
|
* index. Useful for animated particles that also pick a random animation strip. */
|
||||||
public static ResourceLocation[][] generateTextures(String stem, int m, int n){
|
public static ResourceLocation[][] generateTextures(String modID, String stem, int m, int n){
|
||||||
|
|
||||||
ResourceLocation[][] textures = new ResourceLocation[m][n];
|
ResourceLocation[][] textures = new ResourceLocation[m][n];
|
||||||
|
|
||||||
for(int i=0; i<m; i++){
|
for(int i=0; i<m; i++){
|
||||||
for(int j=0; j<n; j++){
|
for(int j=0; j<n; j++){
|
||||||
textures[i][j] = new ResourceLocation(Wizardry.MODID, "particle/" + stem + "_" + i + "_" + j);
|
textures[i][j] = new ResourceLocation(modID, "particle/" + stem + "_" + i + "_" + j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ public class LayerFrost implements LayerRenderer<EntityLivingBase> {
|
|||||||
double scaleX = 1, scaleY = 1;
|
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
|
// 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.
|
// (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){
|
if(model.boxList != null && model.boxList.size() >= 1 && model.boxList.get(0) != null){
|
||||||
scaleX = (double)model.boxList.get(0).textureWidth / 16d;
|
scaleX = (double)model.boxList.get(0).textureWidth / 16d;
|
||||||
scaleY = (double)model.boxList.get(0).textureHeight / 16d;
|
scaleY = (double)model.boxList.get(0).textureHeight / 16d;
|
||||||
}else{ // Fallback to model fields; should never be needed
|
}else{ // Fallback to model fields; should never be needed
|
||||||
@@ -121,11 +121,26 @@ public class LayerFrost implements LayerRenderer<EntityLivingBase> {
|
|||||||
}
|
}
|
||||||
GlStateManager.scale(scaleX, scaleY, 1);
|
GlStateManager.scale(scaleX, scaleY, 1);
|
||||||
GlStateManager.matrixMode(GL11.GL_MODELVIEW);
|
GlStateManager.matrixMode(GL11.GL_MODELVIEW);
|
||||||
|
|
||||||
|
boolean headWearHidden = false;
|
||||||
|
boolean bodyWearHidden = false;
|
||||||
|
boolean leftArmWearHidden = false;
|
||||||
|
boolean rightArmWearHidden = false;
|
||||||
|
boolean leftLegWearHidden = false;
|
||||||
|
boolean rightLegWearHidden = false;
|
||||||
|
|
||||||
// Hides the hat layer for bipeds
|
// Hides the hat layer for bipeds
|
||||||
if(this.model instanceof ModelBiped) ((ModelBiped)this.model).bipedHeadwear.isHidden = true;
|
if(this.model instanceof ModelBiped){
|
||||||
|
headWearHidden = ((ModelBiped)this.model).bipedHeadwear.isHidden;
|
||||||
|
((ModelBiped)this.model).bipedHeadwear.isHidden = true;
|
||||||
|
}
|
||||||
|
|
||||||
if(this.model instanceof ModelPlayer){
|
if(this.model instanceof ModelPlayer){
|
||||||
|
bodyWearHidden = ((ModelPlayer)this.model).bipedBodyWear.isHidden;
|
||||||
|
leftArmWearHidden = ((ModelPlayer)this.model).bipedLeftArmwear.isHidden;
|
||||||
|
rightArmWearHidden = ((ModelPlayer)this.model).bipedRightArmwear.isHidden;
|
||||||
|
leftLegWearHidden = ((ModelPlayer)this.model).bipedLeftLegwear.isHidden;
|
||||||
|
rightLegWearHidden = ((ModelPlayer)this.model).bipedRightLegwear.isHidden;
|
||||||
((ModelPlayer)this.model).bipedBodyWear.isHidden = true;
|
((ModelPlayer)this.model).bipedBodyWear.isHidden = true;
|
||||||
((ModelPlayer)this.model).bipedLeftArmwear.isHidden = true;
|
((ModelPlayer)this.model).bipedLeftArmwear.isHidden = true;
|
||||||
((ModelPlayer)this.model).bipedRightArmwear.isHidden = true;
|
((ModelPlayer)this.model).bipedRightArmwear.isHidden = true;
|
||||||
@@ -136,7 +151,15 @@ public class LayerFrost implements LayerRenderer<EntityLivingBase> {
|
|||||||
this.model.setLivingAnimations(entity, limbSwing, limbSwingAmount, partialTicks);
|
this.model.setLivingAnimations(entity, limbSwing, limbSwingAmount, partialTicks);
|
||||||
this.model.render(entity, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scale);
|
this.model.render(entity, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scale);
|
||||||
|
|
||||||
if(this.model instanceof ModelBiped) ((ModelBiped)this.model).bipedHeadwear.isHidden = false;
|
if(this.model instanceof ModelBiped) ((ModelBiped)this.model).bipedHeadwear.isHidden = headWearHidden;
|
||||||
|
|
||||||
|
if(this.model instanceof ModelPlayer){
|
||||||
|
((ModelPlayer)this.model).bipedBodyWear.isHidden = bodyWearHidden;
|
||||||
|
((ModelPlayer)this.model).bipedLeftArmwear.isHidden = leftArmWearHidden;
|
||||||
|
((ModelPlayer)this.model).bipedRightArmwear.isHidden = rightArmWearHidden;
|
||||||
|
((ModelPlayer)this.model).bipedLeftLegwear.isHidden = leftLegWearHidden;
|
||||||
|
((ModelPlayer)this.model).bipedRightLegwear.isHidden = rightLegWearHidden;
|
||||||
|
}
|
||||||
|
|
||||||
// Undoes the texture scaling
|
// Undoes the texture scaling
|
||||||
GlStateManager.matrixMode(GL11.GL_TEXTURE);
|
GlStateManager.matrixMode(GL11.GL_TEXTURE);
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ public class RenderArcaneLock {
|
|||||||
|
|
||||||
GlStateManager.pushMatrix();
|
GlStateManager.pushMatrix();
|
||||||
GlStateManager.enableBlend();
|
GlStateManager.enableBlend();
|
||||||
|
boolean lighting = GL11.glIsEnabled(GL11.GL_LIGHTING);
|
||||||
GlStateManager.disableLighting();
|
GlStateManager.disableLighting();
|
||||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240, 240);
|
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240, 240);
|
||||||
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||||
@@ -62,6 +63,8 @@ public class RenderArcaneLock {
|
|||||||
List<TileEntity> tileentities = new ArrayList<>(world.loadedTileEntityList);
|
List<TileEntity> tileentities = new ArrayList<>(world.loadedTileEntityList);
|
||||||
|
|
||||||
for(TileEntity tileentity : tileentities){
|
for(TileEntity tileentity : tileentities){
|
||||||
|
|
||||||
|
if(tileentity == null) continue; // What the heck VoxelMap
|
||||||
|
|
||||||
if(tileentity.getDistanceSq(origin.x, origin.y, origin.z) <= tileentity.getMaxRenderDistanceSquared()
|
if(tileentity.getDistanceSq(origin.x, origin.y, origin.z) <= tileentity.getMaxRenderDistanceSquared()
|
||||||
&& tileentity.getTileData().hasUniqueId(ArcaneLock.NBT_KEY)){
|
&& tileentity.getTileData().hasUniqueId(ArcaneLock.NBT_KEY)){
|
||||||
@@ -82,7 +85,9 @@ public class RenderArcaneLock {
|
|||||||
|
|
||||||
GlStateManager.disableBlend();
|
GlStateManager.disableBlend();
|
||||||
GlStateManager.enableTexture2D();
|
GlStateManager.enableTexture2D();
|
||||||
GlStateManager.enableLighting();
|
if (lighting) {
|
||||||
|
GlStateManager.enableLighting();
|
||||||
|
}
|
||||||
GlStateManager.disableRescaleNormal();
|
GlStateManager.disableRescaleNormal();
|
||||||
GlStateManager.popMatrix();
|
GlStateManager.popMatrix();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,9 +53,8 @@ public class RenderBlackHole extends Render<EntityBlackHole> {
|
|||||||
(float)blackhole.ticksExisted / 10);
|
(float)blackhole.ticksExisted / 10);
|
||||||
}
|
}
|
||||||
if(blackhole.ticksExisted > blackhole.lifetime - 10){
|
if(blackhole.ticksExisted > blackhole.lifetime - 10){
|
||||||
GlStateManager.scale((float)(blackhole.lifetime - blackhole.ticksExisted) / 10,
|
float scale = Math.max(0, (float)(blackhole.lifetime - blackhole.ticksExisted) / 10);
|
||||||
(float)(blackhole.lifetime - blackhole.ticksExisted) / 10,
|
GlStateManager.scale(scale, scale, scale);
|
||||||
(float)(blackhole.lifetime - blackhole.ticksExisted) / 10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.bindTexture(texture);
|
this.bindTexture(texture);
|
||||||
|
|||||||
@@ -190,7 +190,8 @@ public class CommandCastSpell extends CommandBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(spell.isContinuous){
|
if(spell.isContinuous){
|
||||||
|
// We need not query Spell#canBeCastByDispensers since with commands there's no difference between
|
||||||
|
// a spell that can't be cast positionally and one that can be cast positionally but fails
|
||||||
if(spell.cast(world, origin.x, origin.y, origin.z, direction, 0, duration, modifiers)){
|
if(spell.cast(world, origin.x, origin.y, origin.z, direction, 0, duration, modifiers)){
|
||||||
|
|
||||||
MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(Source.COMMAND, spell, world, origin.x, origin.y, origin.z, direction, modifiers));
|
MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post(Source.COMMAND, spell, world, origin.x, origin.y, origin.z, direction, modifiers));
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ public class CommandDiscoverSpell extends CommandBase {
|
|||||||
if(server.sendCommandFeedback()) sender.sendMessage(
|
if(server.sendCommandFeedback()) sender.sendMessage(
|
||||||
new TextComponentTranslation("commands." + Wizardry.MODID + ":discoverspell.clear", player.getName()));
|
new TextComponentTranslation("commands." + Wizardry.MODID + ":discoverspell.clear", player.getName()));
|
||||||
}else if(all){
|
}else if(all){
|
||||||
data.spellsDiscovered.addAll(Spell.getSpells(Spell.allSpells));
|
data.spellsDiscovered.addAll(Spell.getAllSpells());
|
||||||
if(server.sendCommandFeedback()) sender.sendMessage(
|
if(server.sendCommandFeedback()) sender.sendMessage(
|
||||||
new TextComponentTranslation("commands." + Wizardry.MODID + ":discoverspell.all", player.getName()));
|
new TextComponentTranslation("commands." + Wizardry.MODID + ":discoverspell.all", player.getName()));
|
||||||
}else{
|
}else{
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import electroblob.wizardry.Wizardry;
|
|||||||
import electroblob.wizardry.data.SpellEmitterData;
|
import electroblob.wizardry.data.SpellEmitterData;
|
||||||
import electroblob.wizardry.event.SpellCastEvent;
|
import electroblob.wizardry.event.SpellCastEvent;
|
||||||
import electroblob.wizardry.spell.Spell;
|
import electroblob.wizardry.spell.Spell;
|
||||||
|
import electroblob.wizardry.util.NBTExtras;
|
||||||
import electroblob.wizardry.util.SpellModifiers;
|
import electroblob.wizardry.util.SpellModifiers;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
@@ -129,7 +130,7 @@ public class SpellEmitter implements ITickable {
|
|||||||
nbt.setDouble("z", z);
|
nbt.setDouble("z", z);
|
||||||
nbt.setInteger("direction", direction.getIndex());
|
nbt.setInteger("direction", direction.getIndex());
|
||||||
nbt.setInteger("duration", duration);
|
nbt.setInteger("duration", duration);
|
||||||
nbt.setTag("modifiers", modifiers.toNBT());
|
NBTExtras.storeTagSafely(nbt, "modifiers", modifiers.toNBT());
|
||||||
nbt.setInteger("castingTick", castingTick);
|
nbt.setInteger("castingTick", castingTick);
|
||||||
|
|
||||||
return nbt;
|
return nbt;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import electroblob.wizardry.packet.WizardryPacketHandler;
|
|||||||
import electroblob.wizardry.registry.Spells;
|
import electroblob.wizardry.registry.Spells;
|
||||||
import electroblob.wizardry.spell.None;
|
import electroblob.wizardry.spell.None;
|
||||||
import electroblob.wizardry.spell.Spell;
|
import electroblob.wizardry.spell.Spell;
|
||||||
|
import electroblob.wizardry.util.NBTExtras;
|
||||||
import electroblob.wizardry.util.SpellModifiers;
|
import electroblob.wizardry.util.SpellModifiers;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
@@ -141,7 +142,7 @@ public abstract class BlockCastingData<T extends TileEntity> implements INBTSeri
|
|||||||
|
|
||||||
nbt.setInteger("spell", spell.metadata());
|
nbt.setInteger("spell", spell.metadata());
|
||||||
nbt.setInteger("castingTick", castingTick);
|
nbt.setInteger("castingTick", castingTick);
|
||||||
nbt.setTag("modifiers", modifiers.toNBT());
|
NBTExtras.storeTagSafely(nbt, "modifiers", modifiers.toNBT());
|
||||||
|
|
||||||
return nbt;
|
return nbt;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -166,7 +166,10 @@ public class DispenserCastingData extends BlockCastingData<TileEntityDispenser>
|
|||||||
// This will fire once for each dimension, but since we want dispenser-casting to work in all dimensions,
|
// 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 is correct (the loaded tile entity list will of course be different in each case.
|
||||||
|
|
||||||
for(TileEntity tileentity : event.world.loadedTileEntityList){
|
// Somehow this was throwing a CME, I have no idea why so I'm just going to cheat and copy the list
|
||||||
|
List<TileEntity> tileEntities = new ArrayList<>(event.world.loadedTileEntityList);
|
||||||
|
|
||||||
|
for(TileEntity tileentity : tileEntities){
|
||||||
if(tileentity instanceof TileEntityDispenser){
|
if(tileentity instanceof TileEntityDispenser){
|
||||||
if(DispenserCastingData.get((TileEntityDispenser)tileentity) != null){
|
if(DispenserCastingData.get((TileEntityDispenser)tileentity) != null){
|
||||||
DispenserCastingData.get((TileEntityDispenser)tileentity).update();
|
DispenserCastingData.get((TileEntityDispenser)tileentity).update();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package electroblob.wizardry.data;
|
package electroblob.wizardry.data;
|
||||||
|
|
||||||
|
import electroblob.wizardry.util.NBTExtras;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
@@ -89,7 +90,7 @@ public interface IStoredVariable<T> extends IVariable<T> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(NBTTagCompound nbt, T value){
|
public void write(NBTTagCompound nbt, T value){
|
||||||
if(value != null) nbt.setTag(key, serialiser.apply(value));
|
if(value != null) NBTExtras.storeTagSafely(nbt, key, serialiser.apply(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ public class SpellEmitterData extends WorldSavedData {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NBTTagCompound writeToNBT(NBTTagCompound compound){
|
public NBTTagCompound writeToNBT(NBTTagCompound compound){
|
||||||
compound.setTag("emitters", NBTExtras.listToNBT(emitters, SpellEmitter::toNBT));
|
NBTExtras.storeTagSafely(compound, "emitters", NBTExtras.listToNBT(emitters, SpellEmitter::toNBT));
|
||||||
return compound;
|
return compound;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import electroblob.wizardry.Wizardry;
|
|||||||
import electroblob.wizardry.packet.PacketGlyphData;
|
import electroblob.wizardry.packet.PacketGlyphData;
|
||||||
import electroblob.wizardry.packet.WizardryPacketHandler;
|
import electroblob.wizardry.packet.WizardryPacketHandler;
|
||||||
import electroblob.wizardry.spell.Spell;
|
import electroblob.wizardry.spell.Spell;
|
||||||
|
import electroblob.wizardry.util.NBTExtras;
|
||||||
import net.minecraft.entity.player.EntityPlayerMP;
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
import net.minecraft.nbt.NBTTagList;
|
import net.minecraft.nbt.NBTTagList;
|
||||||
@@ -43,11 +44,11 @@ public class SpellGlyphData extends WorldSavedData {
|
|||||||
/** Generates random names and descriptions for any spells which don't already have them. */
|
/** Generates random names and descriptions for any spells which don't already have them. */
|
||||||
public void generateGlyphNames(World world){
|
public void generateGlyphNames(World world){
|
||||||
|
|
||||||
for(Spell spell : Spell.getSpells(Spell.allSpells)){
|
for(Spell spell : Spell.getAllSpells()){
|
||||||
if(!randomNames.containsKey(spell)) randomNames.put(spell, generateRandomName(world.rand));
|
if(!randomNames.containsKey(spell)) randomNames.put(spell, generateRandomName(world.rand));
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Spell spell : Spell.getSpells(Spell.allSpells)){
|
for(Spell spell : Spell.getAllSpells()){
|
||||||
if(!randomDescriptions.containsKey(spell))
|
if(!randomDescriptions.containsKey(spell))
|
||||||
randomDescriptions.put(spell, generateRandomDescription(world.rand));
|
randomDescriptions.put(spell, generateRandomDescription(world.rand));
|
||||||
}
|
}
|
||||||
@@ -161,7 +162,7 @@ public class SpellGlyphData extends WorldSavedData {
|
|||||||
|
|
||||||
NBTTagList tagList = new NBTTagList();
|
NBTTagList tagList = new NBTTagList();
|
||||||
|
|
||||||
for(Spell spell : Spell.getSpells(Spell.allSpells)){
|
for(Spell spell : Spell.getAllSpells()){
|
||||||
// Much like the enchantments tag for items, this stores a list of spell-id-to-name tag pairs
|
// 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!
|
// The description is now also included; there's no point in making a second compound tag!
|
||||||
NBTTagCompound tag = new NBTTagCompound();
|
NBTTagCompound tag = new NBTTagCompound();
|
||||||
@@ -171,7 +172,7 @@ public class SpellGlyphData extends WorldSavedData {
|
|||||||
tagList.appendTag(tag);
|
tagList.appendTag(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
nbt.setTag("spellGlyphData", tagList);
|
NBTExtras.storeTagSafely(nbt, "spellGlyphData", tagList);
|
||||||
|
|
||||||
return nbt;
|
return nbt;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -515,12 +515,12 @@ public class WizardData implements INBTSerializable<NBTTagCompound> {
|
|||||||
|
|
||||||
NBTTagCompound properties = new NBTTagCompound();
|
NBTTagCompound properties = new NBTTagCompound();
|
||||||
|
|
||||||
properties.setTag("imbuements", NBTExtras.mapToNBT(this.imbuementDurations,
|
NBTExtras.storeTagSafely(properties, "imbuements", NBTExtras.mapToNBT(this.imbuementDurations,
|
||||||
imbuement -> new NBTTagInt(Enchantment.getEnchantmentID((Enchantment)imbuement)), NBTTagInt::new));
|
imbuement -> new NBTTagInt(Enchantment.getEnchantmentID((Enchantment)imbuement)), NBTTagInt::new));
|
||||||
|
|
||||||
// Mmmmmm Java 8....
|
// Mmmmmm Java 8....
|
||||||
properties.setTag("allies", NBTExtras.listToNBT(this.allies, NBTUtil::createUUIDTag));
|
NBTExtras.storeTagSafely(properties, "allies", NBTExtras.listToNBT(this.allies, NBTUtil::createUUIDTag));
|
||||||
properties.setTag("allyNames", NBTExtras.listToNBT(this.allyNames, NBTTagString::new));
|
NBTExtras.storeTagSafely(properties, "allyNames", NBTExtras.listToNBT(this.allyNames, NBTTagString::new));
|
||||||
|
|
||||||
// Might be worth converting this over to WizardryUtilities.listToNBT.
|
// Might be worth converting this over to WizardryUtilities.listToNBT.
|
||||||
int[] spells = new int[this.spellsDiscovered.size()];
|
int[] spells = new int[this.spellsDiscovered.size()];
|
||||||
@@ -531,7 +531,7 @@ public class WizardData implements INBTSerializable<NBTTagCompound> {
|
|||||||
}
|
}
|
||||||
properties.setIntArray("discoveredSpells", spells);
|
properties.setIntArray("discoveredSpells", spells);
|
||||||
|
|
||||||
properties.setTag("recentSpells", NBTExtras.listToNBT(recentSpells, s -> new NBTTagInt(s.metadata())));
|
NBTExtras.storeTagSafely(properties, "recentSpells", NBTExtras.listToNBT(recentSpells, s -> new NBTTagInt(s.metadata())));
|
||||||
|
|
||||||
storedVariables.forEach(k -> k.write(properties, this.spellData.get(k)));
|
storedVariables.forEach(k -> k.write(properties, this.spellData.get(k)));
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import electroblob.wizardry.registry.Spells;
|
|||||||
import electroblob.wizardry.spell.Spell;
|
import electroblob.wizardry.spell.Spell;
|
||||||
import electroblob.wizardry.util.AllyDesignationSystem;
|
import electroblob.wizardry.util.AllyDesignationSystem;
|
||||||
import electroblob.wizardry.util.MagicDamage;
|
import electroblob.wizardry.util.MagicDamage;
|
||||||
|
import electroblob.wizardry.util.NBTExtras;
|
||||||
import electroblob.wizardry.util.WizardryUtilities;
|
import electroblob.wizardry.util.WizardryUtilities;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
@@ -183,7 +184,7 @@ public class EntityLevitatingBlock extends EntityFallingBlock implements IEntity
|
|||||||
NBTBase nbtbase = this.tileEntityData.getTag(s);
|
NBTBase nbtbase = this.tileEntityData.getTag(s);
|
||||||
|
|
||||||
if(!"x".equals(s) && !"y".equals(s) && !"z".equals(s)){
|
if(!"x".equals(s) && !"y".equals(s) && !"z".equals(s)){
|
||||||
nbttagcompound.setTag(s, nbtbase.copy());
|
NBTExtras.storeTagSafely(nbttagcompound, s, nbtbase.copy());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public class EntityBubble extends EntityMagicConstruct {
|
|||||||
if(isDarkOrb){
|
if(isDarkOrb){
|
||||||
|
|
||||||
if(WizardryUtilities.getRider(this) != null
|
if(WizardryUtilities.getRider(this) != null
|
||||||
&& this.ticksExisted % Spells.entrapment.getProperty(Entrapment.DAMAGE_INTERVAL).intValue() == 0){
|
&& WizardryUtilities.getRider(this).ticksExisted % Spells.entrapment.getProperty(Entrapment.DAMAGE_INTERVAL).intValue() == 0){
|
||||||
if(this.getCaster() != null){
|
if(this.getCaster() != null){
|
||||||
WizardryUtilities.getRider(this).attackEntityFrom(
|
WizardryUtilities.getRider(this).attackEntityFrom(
|
||||||
MagicDamage.causeIndirectMagicDamage(this, getCaster(), DamageType.MAGIC),
|
MagicDamage.causeIndirectMagicDamage(this, getCaster(), DamageType.MAGIC),
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package electroblob.wizardry.entity.construct;
|
package electroblob.wizardry.entity.construct;
|
||||||
|
|
||||||
import electroblob.wizardry.Wizardry;
|
|
||||||
import electroblob.wizardry.registry.Spells;
|
import electroblob.wizardry.registry.Spells;
|
||||||
import electroblob.wizardry.spell.Spell;
|
import electroblob.wizardry.spell.Spell;
|
||||||
import electroblob.wizardry.util.WizardryUtilities;
|
import electroblob.wizardry.util.WizardryUtilities;
|
||||||
|
|||||||
@@ -80,8 +80,8 @@ public class EntityHammer extends EntityMagicConstruct {
|
|||||||
|
|
||||||
if(this.world.isRemote && this.ticksExisted % 3 == 0){
|
if(this.world.isRemote && this.ticksExisted % 3 == 0){
|
||||||
ParticleBuilder.create(Type.SPARK)
|
ParticleBuilder.create(Type.SPARK)
|
||||||
.pos(this.posX - 0.5d + rand.nextDouble(), this.posY + 2 * rand.nextDouble(), this.posZ - 0.5d + rand.nextDouble())
|
.pos(this.posX - 0.5d + rand.nextDouble(), this.posY + 2 * rand.nextDouble(), this.posZ - 0.5d + rand.nextDouble())
|
||||||
.spawn(world);
|
.spawn(world);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.prevPosX = this.posX;
|
this.prevPosX = this.posX;
|
||||||
@@ -103,39 +103,37 @@ public class EntityHammer extends EntityMagicConstruct {
|
|||||||
this.rotationPitch = 0;
|
this.rotationPitch = 0;
|
||||||
this.spin = false;
|
this.spin = false;
|
||||||
|
|
||||||
if(this.ticksExisted % Spells.lightning_hammer.getProperty(LightningHammer.ATTACK_INTERVAL).floatValue() == 0){
|
double seekerRange = Spells.lightning_hammer.getProperty(Spell.EFFECT_RADIUS).doubleValue();
|
||||||
|
|
||||||
double seekerRange = Spells.lightning_hammer.getProperty(Spell.EFFECT_RADIUS).doubleValue();
|
List<EntityLivingBase> targets = WizardryUtilities.getEntitiesWithinRadius(seekerRange, this.posX,
|
||||||
|
this.posY + 1, this.posZ, world);
|
||||||
|
|
||||||
List<EntityLivingBase> targets = WizardryUtilities.getEntitiesWithinRadius(seekerRange, this.posX,
|
int maxTargets = Spells.lightning_hammer.getProperty(LightningHammer.SECONDARY_MAX_TARGETS).intValue();
|
||||||
this.posY + 1, this.posZ, world);
|
while(targets.size() > maxTargets) targets.remove(targets.size() - 1);
|
||||||
|
|
||||||
int maxTargets = Spells.lightning_hammer.getProperty(LightningHammer.SECONDARY_MAX_TARGETS).intValue();
|
for(EntityLivingBase target : targets){
|
||||||
while(targets.size() > maxTargets) targets.remove(targets.size() - 1);
|
|
||||||
|
|
||||||
for(EntityLivingBase target : targets){
|
if(WizardryUtilities.isLiving(target) && this.isValidTarget(target)
|
||||||
|
&& target.ticksExisted % Spells.lightning_hammer.getProperty(LightningHammer.ATTACK_INTERVAL).floatValue() == 0){
|
||||||
|
|
||||||
if(WizardryUtilities.isLiving(target) && this.isValidTarget(target)){
|
if(world.isRemote){
|
||||||
|
|
||||||
if(world.isRemote){
|
ParticleBuilder.create(Type.LIGHTNING).pos(posX, posY + height - 0.1, posZ) .target(target).spawn(world);
|
||||||
|
|
||||||
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);
|
||||||
|
}
|
||||||
|
|
||||||
ParticleBuilder.spawnShockParticles(world, target.posX,
|
target.playSound(WizardrySounds.ENTITY_HAMMER_ATTACK, 1.0F, rand.nextFloat() * 0.4F + 1.5F);
|
||||||
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;
|
||||||
|
|
||||||
float damage = Spells.lightning_hammer.getProperty(Spell.SPLASH_DAMAGE).floatValue() * damageMultiplier;
|
if(this.getCaster() != null){
|
||||||
|
WizardryUtilities.attackEntityWithoutKnockback(target, MagicDamage.causeIndirectMagicDamage(
|
||||||
if(this.getCaster() != null){
|
this, getCaster(), DamageType.SHOCK), damage);
|
||||||
WizardryUtilities.attackEntityWithoutKnockback(target, MagicDamage.causeIndirectMagicDamage(
|
WizardryUtilities.applyStandardKnockback(this, target);
|
||||||
this, getCaster(), DamageType.SHOCK), damage);
|
}else{
|
||||||
WizardryUtilities.applyStandardKnockback(this, target);
|
target.attackEntityFrom(DamageSource.MAGIC, damage);
|
||||||
}else{
|
|
||||||
target.attackEntityFrom(DamageSource.MAGIC, damage);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ public class EntityHealAura extends EntityMagicConstruct {
|
|||||||
target.motionZ = velZ;
|
target.motionZ = velZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
}else if(target.getHealth() < target.getMaxHealth() && this.ticksExisted % 5 == 0){
|
}else if(target.getHealth() < target.getMaxHealth() && target.ticksExisted % 5 == 0){
|
||||||
target.heal(Spells.healing_aura.getProperty(Spell.HEALTH).floatValue() * damageMultiplier);
|
target.heal(Spells.healing_aura.getProperty(Spell.HEALTH).floatValue() * damageMultiplier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,9 +29,9 @@ public class EntityIceSpike extends EntityMagicConstruct {
|
|||||||
this.setRotation(-facing.getHorizontalAngle(), WizardryUtilities.getPitch(facing));
|
this.setRotation(-facing.getHorizontalAngle(), WizardryUtilities.getPitch(facing));
|
||||||
float yaw = (-facing.getHorizontalAngle()) * (float)Math.PI/180;
|
float yaw = (-facing.getHorizontalAngle()) * (float)Math.PI/180;
|
||||||
float pitch = (WizardryUtilities.getPitch(facing) - 90) * (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 min = this.getPositionVector().add(new Vec3d(-width/2, 0, -width/2).rotatePitch(pitch).rotateYaw(yaw));
|
||||||
Vec3d max = new Vec3d(width/2, height, width/2).rotatePitch(pitch).rotateYaw(yaw);
|
Vec3d max = this.getPositionVector().add(new Vec3d(width/2, height, width/2).rotatePitch(pitch).rotateYaw(yaw));
|
||||||
this.setEntityBoundingBox(new AxisAlignedBB(this.getPositionVector().add(min), this.getPositionVector().add(max)));
|
this.setEntityBoundingBox(new AxisAlignedBB(min.x, min.y, min.z, max.x, max.y, max.z));
|
||||||
}
|
}
|
||||||
|
|
||||||
public EnumFacing getFacing(){
|
public EnumFacing getFacing(){
|
||||||
|
|||||||
@@ -213,6 +213,7 @@ public class EntityAIAttackSpell<T extends EntityLiving & ISpellCaster> extends
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is only called when spell casting starts so ticksInUse is always zero
|
||||||
if(spell.cast(attacker.world, attacker, EnumHand.MAIN_HAND, 0, target, modifiers)){
|
if(spell.cast(attacker.world, attacker, EnumHand.MAIN_HAND, 0, target, modifiers)){
|
||||||
|
|
||||||
if(spell.isContinuous){
|
if(spell.isContinuous){
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity
|
|||||||
// Field implementations
|
// Field implementations
|
||||||
private List<Spell> spells = new ArrayList<Spell>(4);
|
private List<Spell> spells = new ArrayList<Spell>(4);
|
||||||
private Spell continuousSpell;
|
private Spell continuousSpell;
|
||||||
|
private int spellCounter;
|
||||||
|
|
||||||
public EntityEvilWizard(World world){
|
public EntityEvilWizard(World world){
|
||||||
|
|
||||||
@@ -175,6 +176,16 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity
|
|||||||
public Spell getContinuousSpell(){
|
public Spell getContinuousSpell(){
|
||||||
return this.continuousSpell;
|
return this.continuousSpell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSpellCounter(int count){
|
||||||
|
spellCounter = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSpellCounter(){
|
||||||
|
return spellCounter;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getAimingError(EnumDifficulty difficulty){
|
public int getAimingError(EnumDifficulty difficulty){
|
||||||
@@ -252,7 +263,7 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity
|
|||||||
// When right-clicked with a spell book in creative, sets one of the spells to that spell
|
// When right-clicked with a spell book in creative, sets one of the spells to that spell
|
||||||
if(player.isCreative() && stack.getItem() instanceof ItemSpellBook){
|
if(player.isCreative() && stack.getItem() instanceof ItemSpellBook){
|
||||||
Spell spell = Spell.byMetadata(stack.getItemDamage());
|
Spell spell = Spell.byMetadata(stack.getItemDamage());
|
||||||
if(this.spells.size() >= 4 && spell.canBeCastByNPCs()){
|
if(this.spells.size() >= 4 && spell.canBeCastBy(this, true)){
|
||||||
// The set(...) method returns the element that was replaced - neat!
|
// The set(...) method returns the element that was replaced - neat!
|
||||||
player.sendMessage(new TextComponentTranslation("item." + Wizardry.MODID + ":spell_book.apply_to_wizard",
|
player.sendMessage(new TextComponentTranslation("item." + Wizardry.MODID + ":spell_book.apply_to_wizard",
|
||||||
this.getDisplayName(), this.spells.set(rand.nextInt(3) + 1, spell).getNameForTranslationFormatted(),
|
this.getDisplayName(), this.spells.set(rand.nextInt(3) + 1, spell).getNameForTranslationFormatted(),
|
||||||
@@ -269,9 +280,9 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity
|
|||||||
super.writeEntityToNBT(nbt);
|
super.writeEntityToNBT(nbt);
|
||||||
nbt.setInteger("element", this.getElement().ordinal());
|
nbt.setInteger("element", this.getElement().ordinal());
|
||||||
nbt.setInteger("skin", this.textureIndex);
|
nbt.setInteger("skin", this.textureIndex);
|
||||||
nbt.setTag("spells", NBTExtras.listToNBT(spells, spell -> new NBTTagInt(spell.metadata())));
|
NBTExtras.storeTagSafely(nbt, "spells", NBTExtras.listToNBT(spells, spell -> new NBTTagInt(spell.metadata())));
|
||||||
nbt.setBoolean("hasStructure", this.hasStructure);
|
nbt.setBoolean("hasStructure", this.hasStructure);
|
||||||
nbt.setTag("groupUUIDs", NBTExtras.listToNBT(groupUUIDs, NBTUtil::createUUIDTag));
|
NBTExtras.storeTagSafely(nbt, "groupUUIDs", NBTExtras.listToNBT(groupUUIDs, NBTUtil::createUUIDTag));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -369,7 +380,7 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity
|
|||||||
// All wizards know magic missile, even if it is disabled.
|
// All wizards know magic missile, even if it is disabled.
|
||||||
spells.add(Spells.magic_missile);
|
spells.add(Spells.magic_missile);
|
||||||
|
|
||||||
Tier maxTier = EntityWizard.populateSpells(spells, element, hasStructure, 3, rand);
|
Tier maxTier = EntityWizard.populateSpells(this, 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;
|
// 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.
|
// it picks a random wand which is at least a high enough tier for the spells the wizard has.
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public class EntityIceGiant extends EntityIronGolem implements ISummonedCreature
|
|||||||
this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F));
|
this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F));
|
||||||
this.tasks.addTask(7, new EntityAILookIdle(this));
|
this.tasks.addTask(7, new EntityAILookIdle(this));
|
||||||
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false));
|
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false));
|
||||||
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget<EntityLivingBase>(this, EntityLivingBase.class,
|
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget<>(this, EntityLivingBase.class,
|
||||||
0, false, true, this.getTargetSelector()));
|
0, false, true, this.getTargetSelector()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,9 +19,6 @@ import net.minecraftforge.fml.common.eventhandler.Event;
|
|||||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.function.IntPredicate;
|
|
||||||
|
|
||||||
@Mod.EventBusSubscriber
|
@Mod.EventBusSubscriber
|
||||||
public class EntityLightningWraith extends EntityBlazeMinion {
|
public class EntityLightningWraith extends EntityBlazeMinion {
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ public class EntityPhoenix extends EntitySummonedCreature implements ISpellCaste
|
|||||||
private EntityAIAttackSpell<EntityPhoenix> spellAttackAI = new EntityAIAttackSpell<>(this, AISpeed, 15f, 60, 140);
|
private EntityAIAttackSpell<EntityPhoenix> spellAttackAI = new EntityAIAttackSpell<>(this, AISpeed, 15f, 60, 140);
|
||||||
|
|
||||||
private Spell continuousSpell;
|
private Spell continuousSpell;
|
||||||
|
private int spellCounter;
|
||||||
|
|
||||||
private static final List<Spell> attack = Collections.singletonList(Spells.flame_ray);
|
private static final List<Spell> attack = Collections.singletonList(Spells.flame_ray);
|
||||||
|
|
||||||
@@ -50,7 +51,7 @@ public class EntityPhoenix extends EntitySummonedCreature implements ISpellCaste
|
|||||||
this.tasks.addTask(3, new EntityAILookIdle(this));
|
this.tasks.addTask(3, new EntityAILookIdle(this));
|
||||||
// this.targetTasks.addTask(0, new EntityAIMoveTowardsTarget(this, 1, 10));
|
// this.targetTasks.addTask(0, new EntityAIMoveTowardsTarget(this, 1, 10));
|
||||||
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true));
|
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true));
|
||||||
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget<EntityLivingBase>(this, EntityLivingBase.class,
|
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget<>(this, EntityLivingBase.class,
|
||||||
0, false, true, this.getTargetSelector()));
|
0, false, true, this.getTargetSelector()));
|
||||||
|
|
||||||
this.setAIMoveSpeed((float)AISpeed);
|
this.setAIMoveSpeed((float)AISpeed);
|
||||||
@@ -76,6 +77,16 @@ public class EntityPhoenix extends EntitySummonedCreature implements ISpellCaste
|
|||||||
continuousSpell = spell;
|
continuousSpell = spell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSpellCounter(int count){
|
||||||
|
spellCounter = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSpellCounter(){
|
||||||
|
return spellCounter;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasRangedAttack(){
|
public boolean hasRangedAttack(){
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public class EntityShadowWraith extends EntitySummonedCreature implements ISpell
|
|||||||
this.tasks.addTask(2, new EntityAIWander(this, AISpeed));
|
this.tasks.addTask(2, new EntityAIWander(this, AISpeed));
|
||||||
this.tasks.addTask(3, new EntityAILookIdle(this));
|
this.tasks.addTask(3, new EntityAILookIdle(this));
|
||||||
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true));
|
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true));
|
||||||
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget<EntityLivingBase>(this, EntityLivingBase.class,
|
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget<>(this, EntityLivingBase.class,
|
||||||
0, false, true, this.getTargetSelector()));
|
0, false, true, this.getTargetSelector()));
|
||||||
|
|
||||||
this.setAIMoveSpeed((float)AISpeed);
|
this.setAIMoveSpeed((float)AISpeed);
|
||||||
@@ -61,21 +61,6 @@ public class EntityShadowWraith extends EntitySummonedCreature implements ISpell
|
|||||||
return attack;
|
return attack;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public SpellModifiers getModifiers(){
|
|
||||||
return new SpellModifiers();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Spell getContinuousSpell(){
|
|
||||||
return Spells.none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setContinuousSpell(Spell spell){
|
|
||||||
// Doesn't use continuous spells.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void applyEntityAttributes(){
|
protected void applyEntityAttributes(){
|
||||||
super.applyEntityAttributes();
|
super.applyEntityAttributes();
|
||||||
|
|||||||
@@ -59,21 +59,6 @@ public class EntityStormElemental extends EntitySummonedCreature implements ISpe
|
|||||||
return attack;
|
return attack;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public SpellModifiers getModifiers(){
|
|
||||||
return new SpellModifiers();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Spell getContinuousSpell(){
|
|
||||||
return Spells.none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setContinuousSpell(Spell spell){
|
|
||||||
// Doesn't use continuous spells.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void applyEntityAttributes(){
|
protected void applyEntityAttributes(){
|
||||||
super.applyEntityAttributes();
|
super.applyEntityAttributes();
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
|
|||||||
// Field implementations
|
// Field implementations
|
||||||
private List<Spell> spells = new ArrayList<Spell>(4);
|
private List<Spell> spells = new ArrayList<Spell>(4);
|
||||||
private Spell continuousSpell;
|
private Spell continuousSpell;
|
||||||
|
private int spellCounter;
|
||||||
|
|
||||||
/** A set of the positions of the blocks that are part of this wizard's tower. */
|
/** A set of the positions of the blocks that are part of this wizard's tower. */
|
||||||
private Set<BlockPos> towerBlocks;
|
private Set<BlockPos> towerBlocks;
|
||||||
@@ -187,7 +188,17 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
|
|||||||
public Spell getContinuousSpell(){
|
public Spell getContinuousSpell(){
|
||||||
return this.continuousSpell;
|
return this.continuousSpell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSpellCounter(int count){
|
||||||
|
spellCounter = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSpellCounter(){
|
||||||
|
return spellCounter;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getAimingError(EnumDifficulty difficulty){
|
public int getAimingError(EnumDifficulty difficulty){
|
||||||
// Being more intelligent than skeletons, wizards are a little more accurate.
|
// Being more intelligent than skeletons, wizards are a little more accurate.
|
||||||
@@ -218,7 +229,8 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
|
|||||||
// Copied from EntityVillager
|
// Copied from EntityVillager
|
||||||
if(!this.world.isRemote && this.livingSoundTime > -this.getTalkInterval() + 20){
|
if(!this.world.isRemote && this.livingSoundTime > -this.getTalkInterval() + 20){
|
||||||
this.livingSoundTime = -this.getTalkInterval();
|
this.livingSoundTime = -this.getTalkInterval();
|
||||||
this.playSound(stack.isEmpty() ? WizardrySounds.ENTITY_WIZARD_NO : WizardrySounds.ENTITY_WIZARD_YES, this.getSoundVolume(), this.getSoundPitch());
|
SoundEvent yes = Wizardry.tisTheSeason ? WizardrySounds.ENTITY_WIZARD_HOHOHO : WizardrySounds.ENTITY_WIZARD_YES;
|
||||||
|
this.playSound(stack.isEmpty() ? WizardrySounds.ENTITY_WIZARD_NO : yes, this.getSoundVolume(), this.getSoundPitch());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,6 +268,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected SoundEvent getAmbientSound(){
|
protected SoundEvent getAmbientSound(){
|
||||||
|
if(Wizardry.tisTheSeason) return WizardrySounds.ENTITY_WIZARD_HOHOHO;
|
||||||
return this.isTrading() ? WizardrySounds.ENTITY_WIZARD_TRADING : WizardrySounds.ENTITY_WIZARD_AMBIENT;
|
return this.isTrading() ? WizardrySounds.ENTITY_WIZARD_TRADING : WizardrySounds.ENTITY_WIZARD_AMBIENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,7 +370,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
|
|||||||
// When right-clicked with a spell book in creative, sets one of the spells to that spell
|
// When right-clicked with a spell book in creative, sets one of the spells to that spell
|
||||||
if(player.isCreative() && stack.getItem() instanceof ItemSpellBook){
|
if(player.isCreative() && stack.getItem() instanceof ItemSpellBook){
|
||||||
Spell spell = Spell.byMetadata(stack.getItemDamage());
|
Spell spell = Spell.byMetadata(stack.getItemDamage());
|
||||||
if(this.spells.size() >= 4 && spell.canBeCastByNPCs()){
|
if(this.spells.size() >= 4 && spell.canBeCastBy(this, true)){
|
||||||
// The set(...) method returns the element that was replaced - neat!
|
// The set(...) method returns the element that was replaced - neat!
|
||||||
player.sendMessage(new TextComponentTranslation("item." + Wizardry.MODID + ":spell_book.apply_to_wizard",
|
player.sendMessage(new TextComponentTranslation("item." + Wizardry.MODID + ":spell_book.apply_to_wizard",
|
||||||
this.getDisplayName(), this.spells.set(rand.nextInt(3) + 1, spell).getNameForTranslationFormatted(),
|
this.getDisplayName(), this.spells.set(rand.nextInt(3) + 1, spell).getNameForTranslationFormatted(),
|
||||||
@@ -387,15 +400,15 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
|
|||||||
super.writeEntityToNBT(nbt);
|
super.writeEntityToNBT(nbt);
|
||||||
|
|
||||||
if(this.trades != null){
|
if(this.trades != null){
|
||||||
nbt.setTag("trades", this.trades.getRecipiesAsTags());
|
NBTExtras.storeTagSafely(nbt, "trades", this.trades.getRecipiesAsTags());
|
||||||
}
|
}
|
||||||
|
|
||||||
nbt.setInteger("element", this.getElement().ordinal());
|
nbt.setInteger("element", this.getElement().ordinal());
|
||||||
nbt.setInteger("skin", this.textureIndex);
|
nbt.setInteger("skin", this.textureIndex);
|
||||||
nbt.setTag("spells", NBTExtras.listToNBT(spells, spell -> new NBTTagInt(spell.metadata())));
|
NBTExtras.storeTagSafely(nbt, "spells", NBTExtras.listToNBT(spells, spell -> new NBTTagInt(spell.metadata())));
|
||||||
|
|
||||||
if(this.towerBlocks != null && this.towerBlocks.size() > 0){
|
if(this.towerBlocks != null && this.towerBlocks.size() > 0){
|
||||||
nbt.setTag("towerBlocks", NBTExtras.listToNBT(this.towerBlocks, NBTUtil::createPosTag));
|
NBTExtras.storeTagSafely(nbt, "towerBlocks", NBTExtras.listToNBT(this.towerBlocks, NBTUtil::createPosTag));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,7 +427,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
|
|||||||
this.spells = (List<Spell>)NBTExtras.NBTToList(nbt.getTagList("spells", NBT.TAG_INT),
|
this.spells = (List<Spell>)NBTExtras.NBTToList(nbt.getTagList("spells", NBT.TAG_INT),
|
||||||
(NBTTagInt tag) -> Spell.byMetadata(tag.getInt()));
|
(NBTTagInt tag) -> Spell.byMetadata(tag.getInt()));
|
||||||
|
|
||||||
NBTTagList tagList = nbt.getTagList("towerBlocks", NBT.TAG_LONG);
|
NBTTagList tagList = nbt.getTagList("towerBlocks", NBT.TAG_COMPOUND);
|
||||||
if(!tagList.isEmpty()){
|
if(!tagList.isEmpty()){
|
||||||
this.towerBlocks = new HashSet<>(NBTExtras.NBTToList(tagList, NBTUtil::getPosFromTag));
|
this.towerBlocks = new HashSet<>(NBTExtras.NBTToList(tagList, NBTUtil::getPosFromTag));
|
||||||
}else{
|
}else{
|
||||||
@@ -750,7 +763,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
|
|||||||
// All wizards know magic missile, even if it is disabled.
|
// All wizards know magic missile, even if it is disabled.
|
||||||
spells.add(Spells.magic_missile);
|
spells.add(Spells.magic_missile);
|
||||||
|
|
||||||
Tier maxTier = populateSpells(spells, element, false, 3, rand);
|
Tier maxTier = populateSpells(this, spells, element, false, 3, rand);
|
||||||
|
|
||||||
// Now done after the spells so it can take the tier into account.
|
// Now done after the spells so it can take the tier into account.
|
||||||
ItemStack wand = new ItemStack(WizardryItems.getWand(maxTier, element));
|
ItemStack wand = new ItemStack(WizardryItems.getWand(maxTier, element));
|
||||||
@@ -767,19 +780,21 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
|
|||||||
/**
|
/**
|
||||||
* Adds n random spells to the given list. The spells will be of the given element if possible. Extracted as a
|
* Adds n random spells to the given list. The spells will be of the given element if possible. Extracted as a
|
||||||
* separate function since it was the same in both EntityWizard and EntityEvilWizard.
|
* separate function since it was the same in both EntityWizard and EntityEvilWizard.
|
||||||
*
|
*
|
||||||
|
* @param wizard The wizard whose spells are to be populated.
|
||||||
* @param spells The spell list to be populated.
|
* @param spells The spell list to be populated.
|
||||||
* @param e The element that the spells should belong to, or {@link Element#MAGIC} for a random element each time.
|
* @param e The element that the spells should belong to, or {@link Element#MAGIC} for a random element each time.
|
||||||
|
* @param master Whether to include master spells.
|
||||||
* @param n The number of spells to add.
|
* @param n The number of spells to add.
|
||||||
* @param random A random number generator to use.
|
* @param random A random number generator to use.
|
||||||
* @return The tier of the highest-tier spell that was added to the list.
|
* @return The tier of the highest-tier spell that was added to the list.
|
||||||
*/
|
*/
|
||||||
static Tier populateSpells(List<Spell> spells, Element e, boolean master, int n, Random random){
|
static Tier populateSpells(final EntityLiving wizard, List<Spell> spells, Element e, boolean master, int n, Random random){
|
||||||
|
|
||||||
// This is the tier of the highest tier spell added.
|
// This is the tier of the highest tier spell added.
|
||||||
Tier maxTier = Tier.NOVICE;
|
Tier maxTier = Tier.NOVICE;
|
||||||
|
|
||||||
List<Spell> npcSpells = Spell.getSpells(Spell.npcSpells);
|
List<Spell> npcSpells = Spell.getSpells(s -> s.canBeCastBy(wizard, false));
|
||||||
npcSpells.removeIf(s -> !s.applicableForItem(WizardryItems.spell_book));
|
npcSpells.removeIf(s -> !s.applicableForItem(WizardryItems.spell_book));
|
||||||
|
|
||||||
for(int i = 0; i < n; i++){
|
for(int i = 0; i < n; i++){
|
||||||
|
|||||||
@@ -19,7 +19,9 @@ import java.util.List;
|
|||||||
* packets) is handled by that class, and all the implementor needs to do is decide which spell(s) to select.
|
* packets) is handled by that class, and all the implementor needs to do is decide which spell(s) to select.
|
||||||
* <p></p>
|
* <p></p>
|
||||||
* This class also allows Wizardry to do all the syncing necessary for continuous spell casting. All the implementor
|
* 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.
|
* needs to do is store the actual fields involved, by implementing {@link ISpellCaster#setContinuousSpell(Spell)},
|
||||||
|
* {@link ISpellCaster#getContinuousSpell()}, {@link ISpellCaster#setSpellCounter(int)}, {@link ISpellCaster#getSpellCounter()}
|
||||||
|
* and {@link ISpellCaster#getModifiers()}.
|
||||||
*/
|
*/
|
||||||
/* Perhaps this should be a capability? Though I can't help thinking they're mainly for attaching data to vanilla
|
/* Perhaps this should be a capability? Though I can't help thinking they're mainly for attaching data to vanilla
|
||||||
* classes, rather than custom ones. For now, the main purpose of this is to centralise code within wizardry itself, and
|
* classes, rather than custom ones. For now, the main purpose of this is to centralise code within wizardry itself, and
|
||||||
@@ -36,10 +38,10 @@ public interface ISpellCaster {
|
|||||||
*
|
*
|
||||||
* @return A list of {@link Spell} instances. A random spell from this list will be cast when the entity attacks.
|
* @return A list of {@link Spell} instances. A random spell from this list will be cast when the entity attacks.
|
||||||
* The list will not be modified by the AI class and can therefore be an immutable list. The spells in the
|
* The list will not be modified by the AI class and can therefore be an immutable list. The spells in the
|
||||||
* list <b>must</b> be castable by NPCs (i.e. {@link Spell#canBeCastByNPCs()} returns true).
|
* list <b>must</b> be castable by NPCs (i.e. {@link Spell#canBeCastBy(net.minecraft.entity.EntityLiving, boolean)} returns true).
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public List<Spell> getSpells();
|
List<Spell> getSpells();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called each time the entity attacks to get the modifiers to apply to the spell.
|
* Called each time the entity attacks to get the modifiers to apply to the spell.
|
||||||
@@ -48,31 +50,47 @@ public interface ISpellCaster {
|
|||||||
* required, pass in an empty {@code SpellModifiers} object.
|
* required, pass in an empty {@code SpellModifiers} object.
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public SpellModifiers getModifiers();
|
default SpellModifiers getModifiers(){
|
||||||
|
return new SpellModifiers(); // May seem wasteful but this should never be called so it doesn't matter
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the continuous spell that is currently being cast, or the None spell if there is none. Implementors
|
* Returns the continuous spell that is currently being cast, or the None spell if there is none. Implementors
|
||||||
* should simply store this as a private field and return it here. Will be synced by the AI class, but whether it is
|
* should simply store this as a private field and return it here. Will be synced by the AI class, but whether it is
|
||||||
* saved to NBT is up to you. If the implementing class does not deal with continuous spells, just return
|
* saved to NBT is up to you. If the implementing class only ever uses one continuous spell, do <b>not</b> just
|
||||||
* {@link Spells#none}. If the implementing class only ever uses one continuous spell, do <b>not</b> just return
|
* return that spell; the field must still be stored.
|
||||||
* that spell; the field must still be stored.
|
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
public Spell getContinuousSpell();
|
default Spell getContinuousSpell(){
|
||||||
|
return Spells.none;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the continuous spell that is currently being cast, or the None spell if there is none. Implementors should
|
* Sets the continuous spell that is currently being cast, or the None spell if there is none. Implementors should
|
||||||
* simply store this as a private field and assign it here. Will be synced by the AI class, but whether it is saved
|
* simply store this as a private field and assign it here. Will be synced by the AI class, but whether it is saved
|
||||||
* to NBT is up to you. If the implementing class does not deal with continuous spells, leave this method blank.
|
* to NBT is up to you. If the implementing class does not deal with continuous spells, leave this method blank.
|
||||||
*/
|
*/
|
||||||
public void setContinuousSpell(Spell spell);
|
default void setContinuousSpell(Spell spell){
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the number of ticks the current spell has been cast for. Implementors should simply store this as a
|
||||||
|
* private field and return it here. This is only used client-side. */
|
||||||
|
default int getSpellCounter(){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sets the number of ticks the current spell has been cast for. Implementors should simply store this as a
|
||||||
|
* private field and assign it here. This is only used client-side. */
|
||||||
|
default void setSpellCounter(int count){
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the aiming arror for the given difficulty, used in projectile spells. Defaults to the values used by
|
* Returns the aiming error for the given difficulty, used in projectile spells. Defaults to the values used by
|
||||||
* skeletons, which are: Easy - 10, Normal - 6, Hard - 2, Peaceful - 10 (rarely used).
|
* skeletons, which are: Easy - 10, Normal - 6, Hard - 2, Peaceful - 10 (rarely used).
|
||||||
*/
|
*/
|
||||||
// This is what default methods are actually intended for!
|
default int getAimingError(EnumDifficulty difficulty) {
|
||||||
public default int getAimingError(EnumDifficulty difficulty) {
|
|
||||||
return WizardryUtilities.getDefaultAimingError(difficulty);
|
return WizardryUtilities.getDefaultAimingError(difficulty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -221,7 +221,8 @@ public interface ISummonedCreature extends IEntityAdditionalSpawnData, IEntityOw
|
|||||||
* possible for implementors to override this in order to do something special when selecting a target.
|
* possible for implementors to override this in order to do something special when selecting a target.
|
||||||
*/
|
*/
|
||||||
default Predicate<Entity> getTargetSelector(){
|
default Predicate<Entity> getTargetSelector(){
|
||||||
return entity -> getCaster() == null ? entity instanceof EntityPlayer : !entity.isInvisible() && isValidTarget(entity);
|
return entity -> !entity.isInvisible() && (getCaster() == null ? entity instanceof EntityPlayer &&
|
||||||
|
!((EntityPlayer)entity).isCreative() : isValidTarget(entity));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -9,11 +9,15 @@ import electroblob.wizardry.util.ParticleBuilder;
|
|||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.EntityLiving;
|
import net.minecraft.entity.EntityLiving;
|
||||||
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.entity.projectile.EntitySmallFireball;
|
import net.minecraft.entity.projectile.EntitySmallFireball;
|
||||||
import net.minecraft.init.Blocks;
|
import net.minecraft.init.Blocks;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraft.util.DamageSource;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.RayTraceResult;
|
import net.minecraft.util.math.RayTraceResult;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
|
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
|
||||||
import net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
@@ -131,6 +135,54 @@ public class EntityMagicFireball extends EntityMagicProjectile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canBeCollidedWith(){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getCollisionBorderSize(){
|
||||||
|
return 1.0F;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean attackEntityFrom(DamageSource source, float amount){
|
||||||
|
|
||||||
|
if(this.isEntityInvulnerable(source)){
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}else{
|
||||||
|
|
||||||
|
this.markVelocityChanged();
|
||||||
|
|
||||||
|
if(source.getTrueSource() != null){
|
||||||
|
|
||||||
|
Vec3d vec3d = source.getTrueSource().getLookVec();
|
||||||
|
|
||||||
|
if(vec3d != null){
|
||||||
|
|
||||||
|
double speed = MathHelper.sqrt(motionX * motionX + motionY * motionY + motionZ * motionZ);
|
||||||
|
|
||||||
|
this.motionX = vec3d.x * speed;
|
||||||
|
this.motionY = vec3d.y * speed;
|
||||||
|
this.motionZ = vec3d.z * speed;
|
||||||
|
|
||||||
|
this.lifetime = 160;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(source.getTrueSource() instanceof EntityLivingBase){
|
||||||
|
this.setCaster((EntityLivingBase)source.getTrueSource());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setLifetime(int lifetime){
|
public void setLifetime(int lifetime){
|
||||||
this.lifetime = lifetime;
|
this.lifetime = lifetime;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package electroblob.wizardry.entity.projectile;
|
package electroblob.wizardry.entity.projectile;
|
||||||
|
|
||||||
|
import electroblob.wizardry.Wizardry;
|
||||||
import electroblob.wizardry.registry.Spells;
|
import electroblob.wizardry.registry.Spells;
|
||||||
import electroblob.wizardry.registry.WizardrySounds;
|
import electroblob.wizardry.registry.WizardrySounds;
|
||||||
import electroblob.wizardry.spell.Spell;
|
import electroblob.wizardry.spell.Spell;
|
||||||
@@ -44,15 +45,34 @@ public class EntityMagicMissile extends EntityMagicArrow {
|
|||||||
public void tickInAir(){
|
public void tickInAir(){
|
||||||
|
|
||||||
if(this.world.isRemote){
|
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);
|
if(Wizardry.tisTheSeason){
|
||||||
|
|
||||||
if(this.ticksExisted > 1){ // Don't spawn particles behind where it started!
|
ParticleBuilder.create(Type.SPARKLE, rand, posX, posY, posZ, 0.03, true).clr(0.8f, 0.15f, 0.15f)
|
||||||
double x = posX - motionX/2;
|
.time(20 + rand.nextInt(10)).spawn(world);
|
||||||
double y = posY - motionY/2;
|
|
||||||
double z = posZ - motionZ/2;
|
ParticleBuilder.create(Type.SNOW).pos(posX, posY, posZ).spawn(world);
|
||||||
ParticleBuilder.create(Type.SPARKLE, rand, x, y, z, 0.03, true).clr(1, 1, 0.65f).fade(0.7f, 0, 1)
|
|
||||||
.time(20 + rand.nextInt(10)).spawn(world);
|
if(this.ticksExisted > 1){ // Don't spawn particles behind where it started!
|
||||||
|
double x = posX - motionX / 2;
|
||||||
|
double y = posY - motionY / 2;
|
||||||
|
double z = posZ - motionZ / 2;
|
||||||
|
ParticleBuilder.create(Type.SPARKLE, rand, x, y, z, 0.03, true).clr(0.15f, 0.7f, 0.15f)
|
||||||
|
.time(20 + rand.nextInt(10)).spawn(world);
|
||||||
|
}
|
||||||
|
|
||||||
|
}else{
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if(this.ticksExisted > 1){ // Don't spawn particles behind where it started!
|
||||||
|
double x = posX - motionX / 2;
|
||||||
|
double y = posY - motionY / 2;
|
||||||
|
double z = posZ - motionZ / 2;
|
||||||
|
ParticleBuilder.create(Type.SPARKLE, rand, x, y, z, 0.03, true).clr(1, 1, 0.65f).fade(0.7f, 0, 1)
|
||||||
|
.time(20 + rand.nextInt(10)).spawn(world);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ public abstract class EntityMagicProjectile extends EntityThrowable implements I
|
|||||||
double dy = !this.hasNoGravity() ? target.getEntityBoundingBox().minY + (double)(target.height / 3.0f) - this.posY
|
double dy = !this.hasNoGravity() ? target.getEntityBoundingBox().minY + (double)(target.height / 3.0f) - this.posY
|
||||||
: target.getEntityBoundingBox().minY + (double)(target.height / 2.0f) - this.posY;
|
: target.getEntityBoundingBox().minY + (double)(target.height / 2.0f) - this.posY;
|
||||||
double dz = target.posZ - caster.posZ;
|
double dz = target.posZ - caster.posZ;
|
||||||
double horizontalDistance = (double)MathHelper.sqrt(dx * dx + dz * dz);
|
double horizontalDistance = MathHelper.sqrt(dx * dx + dz * dz);
|
||||||
|
|
||||||
if(horizontalDistance >= 1.0E-7D){
|
if(horizontalDistance >= 1.0E-7D){
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import electroblob.wizardry.util.ParticleBuilder.Type;
|
|||||||
import electroblob.wizardry.util.WizardryUtilities;
|
import electroblob.wizardry.util.WizardryUtilities;
|
||||||
import net.minecraft.entity.EntityLiving;
|
import net.minecraft.entity.EntityLiving;
|
||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
|
||||||
import net.minecraft.init.MobEffects;
|
import net.minecraft.init.MobEffects;
|
||||||
import net.minecraft.potion.PotionEffect;
|
import net.minecraft.potion.PotionEffect;
|
||||||
import net.minecraft.util.EnumParticleTypes;
|
import net.minecraft.util.EnumParticleTypes;
|
||||||
@@ -66,12 +65,11 @@ public class EntitySmokeBomb extends EntityBomb {
|
|||||||
|
|
||||||
for(EntityLivingBase target : targets){
|
for(EntityLivingBase target : targets){
|
||||||
if(target != this.getThrower()){
|
if(target != this.getThrower()){
|
||||||
// Gives the target blindness if it is a player, mind trick otherwise (since this has the desired
|
// Gives the target blindness, and mind trick if it's not a player (since this has the desired
|
||||||
// effect of preventing targeting)
|
// effect of preventing targeting)
|
||||||
if(target instanceof EntityPlayer){
|
target.addPotionEffect(new PotionEffect(MobEffects.BLINDNESS, duration, 0));
|
||||||
target.addPotionEffect(new PotionEffect(MobEffects.BLINDNESS, duration, 0));
|
|
||||||
}else if(target instanceof EntityLiving){
|
if(target instanceof EntityLiving){
|
||||||
// New AI
|
|
||||||
((EntityLiving)target).setAttackTarget(null);
|
((EntityLiving)target).setAttackTarget(null);
|
||||||
target.addPotionEffect(new PotionEffect(WizardryPotions.mind_trick, duration, 0));
|
target.addPotionEffect(new PotionEffect(WizardryPotions.mind_trick, duration, 0));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,8 @@ public interface IConjuredItem {
|
|||||||
*/
|
*/
|
||||||
default int getMaxDamageFromNBT(ItemStack stack, Spell spell){
|
default int getMaxDamageFromNBT(ItemStack stack, Spell spell){
|
||||||
|
|
||||||
|
if(!spell.arePropertiesInitialised()) return 600; // Failsafe, some edge-cases call this during preInit
|
||||||
|
|
||||||
float baseDuration = spell.getProperty(SpellConjuration.ITEM_LIFETIME).floatValue();
|
float baseDuration = spell.getProperty(SpellConjuration.ITEM_LIFETIME).floatValue();
|
||||||
|
|
||||||
if(stack.hasTagCompound() && stack.getTagCompound().hasKey(DURATION_MULTIPLIER_KEY)){
|
if(stack.hasTagCompound() && stack.getTagCompound().hasKey(DURATION_MULTIPLIER_KEY)){
|
||||||
|
|||||||
@@ -61,11 +61,10 @@ public class ItemArcaneTome extends Item {
|
|||||||
|
|
||||||
Tier tier = Tier.values()[stack.getItemDamage()];
|
Tier tier = Tier.values()[stack.getItemDamage()];
|
||||||
Tier tier2 = Tier.values()[stack.getItemDamage() - 1];
|
Tier tier2 = Tier.values()[stack.getItemDamage() - 1];
|
||||||
|
|
||||||
tooltip.add(tier.getDisplayNameWithFormatting());
|
tooltip.add(tier.getDisplayNameWithFormatting());
|
||||||
tooltip.add("\u00A77" + net.minecraft.client.resources.I18n.format("item." + Wizardry.MODID + ":arcane_tome.desc1",
|
Wizardry.proxy.addMultiLineDescription(tooltip, "item." + this.getRegistryName() + ".desc",
|
||||||
tier2.getDisplayNameWithFormatting()));
|
tier2.getDisplayNameWithFormatting() + "\u00A77", tier.getDisplayNameWithFormatting() + "\u00A77");
|
||||||
tooltip.add("\u00A77" + net.minecraft.client.resources.I18n.format("item." + Wizardry.MODID + ":arcane_tome.desc2",
|
|
||||||
tier.getDisplayNameWithFormatting() + "\u00A77"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -639,6 +639,7 @@ public class ItemArtefact extends Item {
|
|||||||
|
|
||||||
WizardryUtilities.getEntitiesWithinRadius(3, player.posX, player.posY, player.posZ, world).stream()
|
WizardryUtilities.getEntitiesWithinRadius(3, player.posX, player.posY, player.posZ, world).stream()
|
||||||
.filter(WizardryUtilities::isLiving)
|
.filter(WizardryUtilities::isLiving)
|
||||||
|
.filter(e -> e != player)
|
||||||
.min(Comparator.comparingDouble(player::getDistanceSq))
|
.min(Comparator.comparingDouble(player::getDistanceSq))
|
||||||
.ifPresent(target -> {
|
.ifPresent(target -> {
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package electroblob.wizardry.item;
|
package electroblob.wizardry.item;
|
||||||
|
|
||||||
|
import electroblob.wizardry.Wizardry;
|
||||||
import electroblob.wizardry.constants.Constants;
|
import electroblob.wizardry.constants.Constants;
|
||||||
import electroblob.wizardry.data.WizardData;
|
import electroblob.wizardry.data.WizardData;
|
||||||
import electroblob.wizardry.registry.Spells;
|
import electroblob.wizardry.registry.Spells;
|
||||||
@@ -11,11 +12,13 @@ import net.minecraft.entity.player.EntityPlayer;
|
|||||||
import net.minecraft.inventory.Slot;
|
import net.minecraft.inventory.Slot;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
public class ItemBlankScroll extends Item implements IWorkbenchItem {
|
public class ItemBlankScroll extends Item implements IWorkbenchItem {
|
||||||
|
|
||||||
public ItemBlankScroll(){
|
public ItemBlankScroll(){
|
||||||
this.setCreativeTab(WizardryTabs.WIZARDRY);
|
this.setCreativeTab(WizardryTabs.WIZARDRY);
|
||||||
|
this.addPropertyOverride(new ResourceLocation("festive"), (s, w, e) -> Wizardry.tisTheSeason ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -45,10 +48,14 @@ public class ItemBlankScroll extends Item implements IWorkbenchItem {
|
|||||||
int cost = spell.getCost() * centre.getStack().getCount();
|
int cost = spell.getCost() * centre.getStack().getCount();
|
||||||
// Continuous spell scrolls require enough mana to cast them for the duration defined in ItemScroll.
|
// Continuous spell scrolls require enough mana to cast them for the duration defined in ItemScroll.
|
||||||
if(spell.isContinuous) cost *= ItemScroll.CASTING_TIME / 20;
|
if(spell.isContinuous) cost *= ItemScroll.CASTING_TIME / 20;
|
||||||
|
|
||||||
|
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() * Constants.MANA_PER_CRYSTAL > cost){
|
if(crystals.getStack().getCount() * manaPerItem > cost){
|
||||||
// Rounds up to the nearest whole crystal
|
// Rounds up to the nearest whole crystal
|
||||||
crystals.decrStackSize(cost / Constants.MANA_PER_CRYSTAL + 1);
|
crystals.decrStackSize(cost / manaPerItem + 1);
|
||||||
centre.putStack(new ItemStack(WizardryItems.scroll, centre.getStack().getCount(), spell.metadata()));
|
centre.putStack(new ItemStack(WizardryItems.scroll, centre.getStack().getCount(), spell.metadata()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package electroblob.wizardry.item;
|
|||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import electroblob.wizardry.registry.Spells;
|
import electroblob.wizardry.registry.Spells;
|
||||||
import electroblob.wizardry.registry.WizardryPotions;
|
import electroblob.wizardry.registry.WizardryPotions;
|
||||||
|
import electroblob.wizardry.spell.Spell;
|
||||||
import electroblob.wizardry.util.MagicDamage;
|
import electroblob.wizardry.util.MagicDamage;
|
||||||
import electroblob.wizardry.util.MagicDamage.DamageType;
|
import electroblob.wizardry.util.MagicDamage.DamageType;
|
||||||
import electroblob.wizardry.util.WizardryUtilities;
|
import electroblob.wizardry.util.WizardryUtilities;
|
||||||
@@ -81,6 +82,12 @@ public class ItemFrostAxe extends ItemAxe implements IConjuredItem {
|
|||||||
stack.setItemDamage(damage + 1);
|
stack.setItemDamage(damage + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Multimap<String, AttributeModifier> getItemAttributeModifiers(EntityEquipmentSlot equipmentSlot){
|
||||||
|
attackDamage = Spells.frost_axe.getProperty(Spell.DAMAGE).floatValue();
|
||||||
|
return super.getItemAttributeModifiers(equipmentSlot);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hitEntity(ItemStack stack, EntityLivingBase target, EntityLivingBase wielder){
|
public boolean hitEntity(ItemStack stack, EntityLivingBase target, EntityLivingBase wielder){
|
||||||
if(!MagicDamage.isEntityImmune(DamageType.FROST, target))
|
if(!MagicDamage.isEntityImmune(DamageType.FROST, target))
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package electroblob.wizardry.item;
|
package electroblob.wizardry.item;
|
||||||
|
|
||||||
import electroblob.wizardry.Wizardry;
|
import electroblob.wizardry.Wizardry;
|
||||||
import electroblob.wizardry.data.SpellGlyphData;
|
|
||||||
import electroblob.wizardry.event.SpellCastEvent;
|
import electroblob.wizardry.event.SpellCastEvent;
|
||||||
import electroblob.wizardry.event.SpellCastEvent.Source;
|
import electroblob.wizardry.event.SpellCastEvent.Source;
|
||||||
import electroblob.wizardry.packet.PacketCastSpell;
|
import electroblob.wizardry.packet.PacketCastSpell;
|
||||||
@@ -14,16 +13,12 @@ import net.minecraft.entity.EntityLivingBase;
|
|||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.util.ActionResult;
|
import net.minecraft.util.*;
|
||||||
import net.minecraft.util.EnumActionResult;
|
|
||||||
import net.minecraft.util.EnumHand;
|
|
||||||
import net.minecraft.util.NonNullList;
|
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraftforge.common.MinecraftForge;
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
|
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
|
||||||
import net.minecraftforge.fml.relauncher.Side;
|
import net.minecraftforge.fml.relauncher.Side;
|
||||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||||
import net.minecraftforge.oredict.OreDictionary;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -37,6 +32,7 @@ public class ItemScroll extends Item implements ISpellCastingItem {
|
|||||||
setHasSubtypes(true);
|
setHasSubtypes(true);
|
||||||
setMaxStackSize(16);
|
setMaxStackSize(16);
|
||||||
setCreativeTab(WizardryTabs.SPELLS);
|
setCreativeTab(WizardryTabs.SPELLS);
|
||||||
|
this.addPropertyOverride(new ResourceLocation("festive"), (s, w, e) -> Wizardry.tisTheSeason ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -54,7 +50,7 @@ public class ItemScroll extends Item implements ISpellCastingItem {
|
|||||||
|
|
||||||
if(tab == WizardryTabs.SPELLS){
|
if(tab == WizardryTabs.SPELLS){
|
||||||
|
|
||||||
List<Spell> spells = Spell.getSpells(Spell.allSpells);
|
List<Spell> spells = Spell.getAllSpells();
|
||||||
spells.removeIf(s -> !s.applicableForItem(this));
|
spells.removeIf(s -> !s.applicableForItem(this));
|
||||||
|
|
||||||
for(Spell spell : spells){
|
for(Spell spell : spells){
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ public class ItemSpellBook extends Item {
|
|||||||
setHasSubtypes(true);
|
setHasSubtypes(true);
|
||||||
setMaxStackSize(16);
|
setMaxStackSize(16);
|
||||||
setCreativeTab(WizardryTabs.SPELLS);
|
setCreativeTab(WizardryTabs.SPELLS);
|
||||||
|
this.addPropertyOverride(new ResourceLocation("festive"), (s, w, e) -> Wizardry.tisTheSeason ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -40,7 +41,7 @@ public class ItemSpellBook extends Item {
|
|||||||
|
|
||||||
if(tab == WizardryTabs.SPELLS){
|
if(tab == WizardryTabs.SPELLS){
|
||||||
|
|
||||||
List<Spell> spells = Spell.getSpells(Spell.allSpells);
|
List<Spell> spells = Spell.getAllSpells();
|
||||||
spells.removeIf(s -> !s.applicableForItem(this));
|
spells.removeIf(s -> !s.applicableForItem(this));
|
||||||
|
|
||||||
for(Spell spell : spells){
|
for(Spell spell : spells){
|
||||||
|
|||||||
@@ -400,7 +400,7 @@ public class ItemWand extends Item implements IWorkbenchItem, ISpellCastingItem,
|
|||||||
if(MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Tick(Source.WAND, spell, caster, modifiers, castingTick))) return false;
|
if(MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Tick(Source.WAND, spell, caster, modifiers, castingTick))) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cost = (int)(spell.getCost() * modifiers.get(SpellModifiers.COST));
|
int cost = (int)(spell.getCost() * modifiers.get(SpellModifiers.COST) + 0.1f); // Weird floaty rounding
|
||||||
|
|
||||||
// As of wizardry 4.2 mana cost is only divided over two intervals each second
|
// As of wizardry 4.2 mana cost is only divided over two intervals each second
|
||||||
if(spell.isContinuous) cost = getDistributedCost(cost, castingTick);
|
if(spell.isContinuous) cost = getDistributedCost(cost, castingTick);
|
||||||
@@ -436,7 +436,7 @@ public class ItemWand extends Item implements IWorkbenchItem, ISpellCastingItem,
|
|||||||
caster.setActiveHand(hand);
|
caster.setActiveHand(hand);
|
||||||
|
|
||||||
// Mana cost
|
// Mana cost
|
||||||
int cost = (int)(spell.getCost() * modifiers.get(SpellModifiers.COST));
|
int cost = (int)(spell.getCost() * modifiers.get(SpellModifiers.COST) + 0.1f); // Weird floaty rounding
|
||||||
// As of wizardry 4.2 mana cost is only divided over two intervals each second
|
// As of wizardry 4.2 mana cost is only divided over two intervals each second
|
||||||
if(spell.isContinuous) cost = getDistributedCost(cost, castingTick);
|
if(spell.isContinuous) cost = getDistributedCost(cost, castingTick);
|
||||||
|
|
||||||
@@ -497,7 +497,7 @@ public class ItemWand extends Item implements IWorkbenchItem, ISpellCastingItem,
|
|||||||
|
|
||||||
int castingTick = stack.getMaxItemUseDuration() - timeLeft; // Might as well include this
|
int castingTick = stack.getMaxItemUseDuration() - timeLeft; // Might as well include this
|
||||||
|
|
||||||
int cost = getDistributedCost((int)(spell.getCost() * modifiers.get(SpellModifiers.COST)), castingTick);
|
int cost = getDistributedCost((int)(spell.getCost() * modifiers.get(SpellModifiers.COST) + 0.1f), castingTick);
|
||||||
|
|
||||||
// Still need to check there's enough mana or the spell will finish twice, since running out of mana is
|
// Still need to check there's enough mana or the spell will finish twice, since running out of mana is
|
||||||
// handled separately.
|
// handled separately.
|
||||||
|
|||||||
@@ -57,12 +57,12 @@ public class ItemWizardArmour extends ItemArmor implements IWorkbenchItem, IMana
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Should only be used by vanilla's armour damage calculations; use {@link ItemWizardArmour#setMana(ItemStack, int)}
|
/** Should only be used by vanilla's armour damage calculations; use {@link ItemWizardArmour#setMana(ItemStack, int)}
|
||||||
* to modify wand mana from elsewhere. */
|
* to modify armour mana from elsewhere. */
|
||||||
@Override
|
@Override
|
||||||
public void setDamage(ItemStack stack, int damage){
|
public void setDamage(ItemStack stack, int damage){
|
||||||
// Overridden to stop repair things from 'repairing' the mana in wizard armour
|
// 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
|
// 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);
|
if(stack.getItemDamage() < damage) super.setDamage(stack, Math.min(damage, stack.getMaxDamage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -178,9 +178,14 @@ public class ItemWizardArmour extends ItemArmor implements IWorkbenchItem, IMana
|
|||||||
|
|
||||||
String s = "wizard_armour";
|
String s = "wizard_armour";
|
||||||
|
|
||||||
if(this.element != null) s = s + "_" + this.element.getName();
|
if(Wizardry.tisTheSeason){
|
||||||
|
s = s + "_festive";
|
||||||
|
}else{
|
||||||
|
if(this.element != null) s = s + "_" + this.element.getName();
|
||||||
|
if(stack.hasTagCompound() && stack.getTagCompound().getBoolean("legendary")) s = "legendary_" + s;
|
||||||
|
}
|
||||||
|
|
||||||
if(slot == EntityEquipmentSlot.LEGS) s = s + "_legs";
|
if(slot == EntityEquipmentSlot.LEGS) s = s + "_legs";
|
||||||
if(stack.hasTagCompound() && stack.getTagCompound().getBoolean("legendary")) s = "legendary_" + s;
|
|
||||||
|
|
||||||
return "ebwizardry:textures/armour/" + s + ".png";
|
return "ebwizardry:textures/armour/" + s + ".png";
|
||||||
}
|
}
|
||||||
@@ -325,7 +330,7 @@ public class ItemWizardArmour extends ItemArmor implements IWorkbenchItem, IMana
|
|||||||
IAttributeInstance attribute = event.getEntityLiving().getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE);
|
IAttributeInstance attribute = event.getEntityLiving().getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE);
|
||||||
double followRange = attribute == null ? 16 : attribute.getAttributeValue();
|
double followRange = attribute == null ? 16 : attribute.getAttributeValue();
|
||||||
if(event.getTarget().isSneaking()) followRange *= 0.8;
|
if(event.getTarget().isSneaking()) followRange *= 0.8;
|
||||||
float f = armourPieces / ((EntityPlayer)event.getTarget()).inventory.armorInventory.size();
|
float f = (float)armourPieces / ((EntityPlayer)event.getTarget()).inventory.armorInventory.size();
|
||||||
if(f < 0.1F) f = 0.1F;
|
if(f < 0.1F) f = 0.1F;
|
||||||
followRange *= (double)(0.7F * f);
|
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
|
// Don't need to worry about the isSuitableTarget check since it must already have been checked to get this far
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ public class BehaviourSpellDispense extends BehaviorDispenseOptional {
|
|||||||
if(world.isSideSolid(source.getBlockPos().offset(direction), direction.getOpposite())) return stack;
|
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 the scroll can never be cast by a dispenser, it should be dispensed as an item.
|
||||||
if(!spell.canBeCastByDispensers()) return super.dispenseStack(source, stack);
|
if(!spell.canBeCastBy(source.getBlockTileEntity())) return super.dispenseStack(source, stack);
|
||||||
|
|
||||||
SpellModifiers modifiers = new SpellModifiers();
|
SpellModifiers modifiers = new SpellModifiers();
|
||||||
|
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
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;
|
|
||||||
|
|
||||||
/** <b>[Server -> Client]</b> 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<PacketEndSlowTime.Message, IMessage> {
|
|
||||||
|
|
||||||
@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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -26,7 +26,6 @@ public class WizardryPacketHandler {
|
|||||||
registerMessage(PacketSpellProperties.class, PacketSpellProperties.Message.class);
|
registerMessage(PacketSpellProperties.class, PacketSpellProperties.Message.class);
|
||||||
registerMessage(PacketSyncAdvancements.class, PacketSyncAdvancements.Message.class);
|
registerMessage(PacketSyncAdvancements.class, PacketSyncAdvancements.Message.class);
|
||||||
registerMessage(PacketRequestAdvancementSync.class, PacketRequestAdvancementSync.Message.class);
|
registerMessage(PacketRequestAdvancementSync.class, PacketRequestAdvancementSync.Message.class);
|
||||||
registerMessage(PacketEndSlowTime.class, PacketEndSlowTime.Message.class);
|
|
||||||
registerMessage(PacketResurrection.class, PacketResurrection.Message.class);
|
registerMessage(PacketResurrection.class, PacketResurrection.Message.class);
|
||||||
registerMessage(PacketCastSpellAtPos.class, PacketCastSpellAtPos.Message.class);
|
registerMessage(PacketCastSpellAtPos.class, PacketCastSpellAtPos.Message.class);
|
||||||
registerMessage(PacketEmitterData.class, PacketEmitterData.Message.class);
|
registerMessage(PacketEmitterData.class, PacketEmitterData.Message.class);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package electroblob.wizardry.potion;
|
|||||||
|
|
||||||
import electroblob.wizardry.Wizardry;
|
import electroblob.wizardry.Wizardry;
|
||||||
import electroblob.wizardry.registry.WizardryPotions;
|
import electroblob.wizardry.registry.WizardryPotions;
|
||||||
|
import electroblob.wizardry.util.NBTExtras;
|
||||||
import electroblob.wizardry.util.WizardryUtilities;
|
import electroblob.wizardry.util.WizardryUtilities;
|
||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.entity.player.EntityPlayerMP;
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
@@ -40,7 +41,7 @@ public class PotionContainment extends PotionMagicEffect {
|
|||||||
|
|
||||||
// Initialise the containment position to the entity's position if it wasn't set already
|
// Initialise the containment position to the entity's position if it wasn't set already
|
||||||
if(!target.getEntityData().hasKey(ENTITY_TAG)){
|
if(!target.getEntityData().hasKey(ENTITY_TAG)){
|
||||||
target.getEntityData().setTag(ENTITY_TAG, NBTUtil.createPosTag(new BlockPos(target.getPositionVector().subtract(0.5, 0.5, 0.5))));
|
NBTExtras.storeTagSafely(target.getEntityData(), 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)));
|
Vec3d origin = WizardryUtilities.getCentre(NBTUtil.getPosFromTag(target.getEntityData().getCompoundTag(ENTITY_TAG)));
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ package electroblob.wizardry.potion;
|
|||||||
|
|
||||||
import electroblob.wizardry.Wizardry;
|
import electroblob.wizardry.Wizardry;
|
||||||
import electroblob.wizardry.item.ItemArtefact;
|
import electroblob.wizardry.item.ItemArtefact;
|
||||||
import electroblob.wizardry.packet.PacketEndSlowTime;
|
|
||||||
import electroblob.wizardry.packet.WizardryPacketHandler;
|
|
||||||
import electroblob.wizardry.registry.Spells;
|
import electroblob.wizardry.registry.Spells;
|
||||||
import electroblob.wizardry.registry.WizardryItems;
|
import electroblob.wizardry.registry.WizardryItems;
|
||||||
import electroblob.wizardry.registry.WizardryPotions;
|
import electroblob.wizardry.registry.WizardryPotions;
|
||||||
@@ -17,11 +15,15 @@ import net.minecraft.entity.IProjectile;
|
|||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.entity.projectile.EntityArrow;
|
import net.minecraft.entity.projectile.EntityArrow;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
import net.minecraft.world.World;
|
||||||
import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent;
|
import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent;
|
||||||
import net.minecraftforge.event.entity.living.PotionEvent;
|
import net.minecraftforge.event.entity.living.PotionEvent;
|
||||||
import net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
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;
|
import java.util.List;
|
||||||
|
|
||||||
@Mod.EventBusSubscriber
|
@Mod.EventBusSubscriber
|
||||||
@@ -29,6 +31,8 @@ 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
|
// FIXME: Minecarts with entities in them (and, I suspect, any other ridden entities) go crazy when time-slowed
|
||||||
|
|
||||||
|
public static final String NBT_KEY = "time_slowed";
|
||||||
|
|
||||||
public PotionSlowTime(boolean isBadEffect, int liquidColour){
|
public PotionSlowTime(boolean isBadEffect, int liquidColour){
|
||||||
super(isBadEffect, liquidColour, new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icon_slow_time.png"));
|
super(isBadEffect, liquidColour, new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icon_slow_time.png"));
|
||||||
this.setPotionName("potion." + Wizardry.MODID + ":slow_time");
|
this.setPotionName("potion." + Wizardry.MODID + ":slow_time");
|
||||||
@@ -61,6 +65,8 @@ public class PotionSlowTime extends PotionMagicEffect implements ISyncedPotion {
|
|||||||
|
|
||||||
for(Entity entity : targetsInRange){
|
for(Entity entity : targetsInRange){
|
||||||
|
|
||||||
|
entity.getEntityData().setBoolean(NBT_KEY, true);
|
||||||
|
|
||||||
// If time is stopped, block all updates; otherwise block all updates except every [interval] ticks
|
// If time is stopped, block all updates; otherwise block all updates except every [interval] ticks
|
||||||
entity.updateBlocked = stopTime || host.ticksExisted % interval != 0;
|
entity.updateBlocked = stopTime || host.ticksExisted % interval != 0;
|
||||||
|
|
||||||
@@ -130,6 +136,29 @@ public class PotionSlowTime extends PotionMagicEffect implements ISyncedPotion {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Goes through every entity in the given world and does the following:<br>
|
||||||
|
* 1. Checks if they have the slow time NBT tag<br>
|
||||||
|
* 2. If so, scans the area nearby for players or NPCs with the slow time effect<br>
|
||||||
|
* 3. If none are found, removes the slow time NBT tag and unblocks the entity's updates
|
||||||
|
*/
|
||||||
|
public static void cleanUpEntities(World world){
|
||||||
|
// Had trouble with accessing loadedTileEntityList from tick events causing random CMEs so I'm making a
|
||||||
|
// copy of this too just in case
|
||||||
|
List<Entity> loadedEntityList = new ArrayList<>(world.loadedEntityList);
|
||||||
|
|
||||||
|
for(Entity entity : loadedEntityList){
|
||||||
|
if(entity.getEntityData().getBoolean(NBT_KEY)){
|
||||||
|
// Currently only players can cast slow time, but you could apply the effect to NPCs with commands
|
||||||
|
List<EntityLivingBase> nearby = WizardryUtilities.getEntitiesWithinRadius(getEffectRadius(), entity.posX, entity.posY, entity.posZ, entity.world, EntityLivingBase.class);
|
||||||
|
if(nearby.stream().noneMatch(e -> e.isPotionActive(WizardryPotions.slow_time))){
|
||||||
|
entity.getEntityData().removeTag(NBT_KEY);
|
||||||
|
entity.updateBlocked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onLivingUpdateEvent(LivingUpdateEvent event){
|
public static void onLivingUpdateEvent(LivingUpdateEvent event){
|
||||||
|
|
||||||
@@ -150,23 +179,16 @@ public class PotionSlowTime extends PotionMagicEffect implements ISyncedPotion {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onPotionExpiryEvent(PotionEvent.PotionExpiryEvent event){
|
public static void tick(TickEvent.WorldTickEvent event){
|
||||||
if(event.getPotionEffect() != null && event.getPotionEffect().getPotion() == WizardryPotions.slow_time){
|
if(!event.world.isRemote && event.phase == TickEvent.Phase.END) cleanUpEntities(event.world);
|
||||||
unblockNearbyEntities(event.getEntityLiving());
|
|
||||||
if(!event.getEntity().world.isRemote){
|
|
||||||
WizardryPacketHandler.net.sendToDimension(new PacketEndSlowTime.Message(event.getEntityLiving()), event.getEntity().dimension);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We still need this as well as tick events because the player hasn't moved anywhere, they just logged out
|
||||||
|
// In fact, it won't really matter since the tick event fixes it on login anyway, but if the mod is uninstalled or
|
||||||
|
// something else weird happens...
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onPotionRemoveEvent(PotionEvent.PotionRemoveEvent event){
|
public static void onPlayerLoggedOutEvent(PlayerEvent.PlayerLoggedOutEvent event){
|
||||||
if(event.getPotionEffect() != null && event.getPotionEffect().getPotion() == WizardryPotions.slow_time){
|
if(event.player.updateBlocked) event.player.updateBlocked = false;
|
||||||
unblockNearbyEntities(event.getEntityLiving());
|
|
||||||
if(!event.getEntity().world.isRemote){
|
|
||||||
WizardryPacketHandler.net.sendToDimension(new PacketEndSlowTime.Message(event.getEntityLiving()), event.getEntity().dimension);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import electroblob.wizardry.entity.construct.*;
|
|||||||
import electroblob.wizardry.entity.living.*;
|
import electroblob.wizardry.entity.living.*;
|
||||||
import electroblob.wizardry.entity.projectile.*;
|
import electroblob.wizardry.entity.projectile.*;
|
||||||
import electroblob.wizardry.spell.*;
|
import electroblob.wizardry.spell.*;
|
||||||
|
import net.minecraft.entity.projectile.EntitySnowball;
|
||||||
import net.minecraft.init.MobEffects;
|
import net.minecraft.init.MobEffects;
|
||||||
import net.minecraft.item.EnumAction;
|
import net.minecraft.item.EnumAction;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
@@ -243,10 +244,15 @@ public final class Spells {
|
|||||||
IForgeRegistry<Spell> registry = event.getRegistry();
|
IForgeRegistry<Spell> registry = event.getRegistry();
|
||||||
|
|
||||||
registry.register(new None());
|
registry.register(new None());
|
||||||
registry.register(new SpellArrow<>("magic_missile", EntityMagicMissile::new).addProperties(Spell.DAMAGE).soundValues(1, 1.4f, 0.4f));
|
registry.register(new SpellArrow<EntityMagicMissile>("magic_missile", EntityMagicMissile::new){
|
||||||
|
@Override
|
||||||
|
protected String getTranslationKey(){
|
||||||
|
return Wizardry.tisTheSeason ? super.getTranslationKey() + "_festive" : super.getTranslationKey();
|
||||||
|
}
|
||||||
|
}.addProperties(Spell.DAMAGE).soundValues(1, 1.4f, 0.4f));
|
||||||
registry.register(new Ignite());
|
registry.register(new Ignite());
|
||||||
registry.register(new Freeze());
|
registry.register(new Freeze());
|
||||||
registry.register(new Snowball());
|
registry.register(new SpellThrowable<>("snowball", EntitySnowball::new).npcSelector((e, o) -> o).soundValues(0.5f, 0.4f, 0.2f)); // Let's spare wizards the pain of the snowball spell
|
||||||
registry.register(new Arc());
|
registry.register(new Arc());
|
||||||
registry.register(new SpellProjectile<>("thunderbolt", EntityThunderbolt::new).addProperties(Spell.DAMAGE, EntityThunderbolt.KNOCKBACK_STRENGTH).soundValues(0.8f, 0.9f, 0.2f));
|
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 SummonZombie());
|
||||||
@@ -316,7 +322,7 @@ public final class Spells {
|
|||||||
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 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 ShadowWard());
|
||||||
registry.register(new Decay());
|
registry.register(new Decay());
|
||||||
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 SpellBuff("water_breathing", 0.3f, 0.3f, 1, () -> MobEffects.WATER_BREATHING).npcSelector((e, o) -> false).soundValues(0.7f, 1.2f, 0.4f));
|
||||||
registry.register(new Tornado());
|
registry.register(new Tornado());
|
||||||
registry.register(new Glide());
|
registry.register(new Glide());
|
||||||
registry.register(new SummonSpiritHorse());
|
registry.register(new SummonSpiritHorse());
|
||||||
@@ -367,7 +373,7 @@ public final class Spells {
|
|||||||
registry.register(new Intimidate());
|
registry.register(new Intimidate());
|
||||||
registry.register(new Banish());
|
registry.register(new Banish());
|
||||||
registry.register(new SixthSense());
|
registry.register(new SixthSense());
|
||||||
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 SpellBuff("darkvision", 0, 0.4f, 0.7f, () -> MobEffects.NIGHT_VISION).npcSelector((e, o) -> false).soundValues(0.7f, 1.2f, 0.4f));
|
||||||
registry.register(new Clairvoyance());
|
registry.register(new Clairvoyance());
|
||||||
registry.register(new PocketWorkbench());
|
registry.register(new PocketWorkbench());
|
||||||
registry.register(new ImbueWeapon());
|
registry.register(new ImbueWeapon());
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import electroblob.wizardry.constants.Tier;
|
|||||||
import electroblob.wizardry.loot.RandomSpell;
|
import electroblob.wizardry.loot.RandomSpell;
|
||||||
import electroblob.wizardry.loot.WizardSpell;
|
import electroblob.wizardry.loot.WizardSpell;
|
||||||
import electroblob.wizardry.spell.Spell;
|
import electroblob.wizardry.spell.Spell;
|
||||||
import net.minecraft.entity.EntityList;
|
|
||||||
import net.minecraft.entity.EnumCreatureType;
|
import net.minecraft.entity.EnumCreatureType;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.world.storage.loot.*;
|
import net.minecraft.world.storage.loot.*;
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ public final class WizardrySounds {
|
|||||||
public static final SoundEvent ENTITY_WIZARD_TRADING = createSound("entity.wizard.trading");
|
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_HURT = createSound("entity.wizard.hurt");
|
||||||
public static final SoundEvent ENTITY_WIZARD_DEATH = createSound("entity.wizard.death");
|
public static final SoundEvent ENTITY_WIZARD_DEATH = createSound("entity.wizard.death");
|
||||||
|
public static final SoundEvent ENTITY_WIZARD_HOHOHO = createSound("entity.wizard.hohoho");
|
||||||
|
|
||||||
public static final SoundEvent ENTITY_DARKNESS_ORB_HIT = createSound("entity.darkness_orb.hit");
|
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 = createSound("entity.dart.hit");
|
||||||
@@ -132,10 +133,17 @@ public final class WizardrySounds {
|
|||||||
public static final SoundEvent MISC_PAGE_TURN = createSound("misc.page_turn");
|
public static final SoundEvent MISC_PAGE_TURN = createSound("misc.page_turn");
|
||||||
public static final SoundEvent MISC_FREEZE = createSound("misc.freeze");
|
public static final SoundEvent MISC_FREEZE = createSound("misc.freeze");
|
||||||
|
|
||||||
/** Trick borrowed from the Twilight Forest, makes things neater. */
|
// Trick borrowed from the Twilight Forest, makes things neater.
|
||||||
|
|
||||||
|
/** Overload for {@link WizardrySounds#createSound(String, String)} which assigns wizardry's mod ID automatically. */
|
||||||
public static SoundEvent createSound(String name){
|
public static SoundEvent createSound(String name){
|
||||||
|
return createSound(Wizardry.MODID, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates a sound with the given name, to be read from {@code assets/[modID]/sounds.json}. */
|
||||||
|
public static SoundEvent createSound(String modID, String name){
|
||||||
// All the setRegistryName methods delegate to this one, it doesn't matter which you use.
|
// All the setRegistryName methods delegate to this one, it doesn't matter which you use.
|
||||||
return new SoundEvent(new ResourceLocation(Wizardry.MODID, name)).setRegistryName(name);
|
return new SoundEvent(new ResourceLocation(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.
|
// For some reason, sound events seem to work even when they aren't registered, without even so much as a warning.
|
||||||
@@ -250,7 +258,7 @@ public final class WizardrySounds {
|
|||||||
event.getRegistry().register(MISC_PAGE_TURN);
|
event.getRegistry().register(MISC_PAGE_TURN);
|
||||||
event.getRegistry().register(MISC_FREEZE);
|
event.getRegistry().register(MISC_FREEZE);
|
||||||
|
|
||||||
for(Spell spell : Spell.getSpells(Spell.allSpells)){
|
for(Spell spell : Spell.getAllSpells()){
|
||||||
event.getRegistry().registerAll(spell.getSounds());
|
event.getRegistry().registerAll(spell.getSounds());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,11 +6,13 @@ import electroblob.wizardry.util.NBTExtras;
|
|||||||
import electroblob.wizardry.util.SpellModifiers;
|
import electroblob.wizardry.util.SpellModifiers;
|
||||||
import electroblob.wizardry.util.WizardryUtilities;
|
import electroblob.wizardry.util.WizardryUtilities;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityLiving;
|
||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.item.EnumAction;
|
import net.minecraft.item.EnumAction;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.tileentity.TileEntityDispenser;
|
||||||
import net.minecraft.util.EnumFacing;
|
import net.minecraft.util.EnumFacing;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
@@ -32,9 +34,9 @@ public class ArcaneLock extends SpellRay {
|
|||||||
|
|
||||||
@Override public boolean requiresPacket(){ return true; }
|
@Override public boolean requiresPacket(){ return true; }
|
||||||
|
|
||||||
@Override public boolean canBeCastByDispensers(){ return false; }
|
@Override public boolean canBeCastBy(TileEntityDispenser dispenser){ return false; }
|
||||||
|
|
||||||
@Override public boolean canBeCastByNPCs(){ return false; }
|
@Override public boolean canBeCastBy(EntityLiving npc, boolean override){ return false; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){
|
protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package electroblob.wizardry.spell;
|
package electroblob.wizardry.spell;
|
||||||
|
|
||||||
|
import electroblob.wizardry.Wizardry;
|
||||||
import electroblob.wizardry.registry.WizardryItems;
|
import electroblob.wizardry.registry.WizardryItems;
|
||||||
import electroblob.wizardry.util.ParticleBuilder;
|
import electroblob.wizardry.util.ParticleBuilder;
|
||||||
import electroblob.wizardry.util.ParticleBuilder.Type;
|
import electroblob.wizardry.util.ParticleBuilder.Type;
|
||||||
@@ -7,6 +8,7 @@ import electroblob.wizardry.util.SpellModifiers;
|
|||||||
import electroblob.wizardry.util.WizardryUtilities;
|
import electroblob.wizardry.util.WizardryUtilities;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.item.EnumAction;
|
import net.minecraft.item.EnumAction;
|
||||||
import net.minecraft.util.EnumFacing;
|
import net.minecraft.util.EnumFacing;
|
||||||
import net.minecraft.util.EnumParticleTypes;
|
import net.minecraft.util.EnumParticleTypes;
|
||||||
@@ -78,9 +80,7 @@ public class Banish extends SpellRay {
|
|||||||
world.rand.nextDouble() - 0.5, 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 instanceof EntityPlayer) Wizardry.proxy.playBlinkEffect((EntityPlayer)entity);
|
||||||
if(entity == net.minecraft.client.Minecraft.getMinecraft().player)
|
|
||||||
electroblob.wizardry.client.WizardryClientEventHandler.playBlinkEffect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(y != null){
|
if(y != null){
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package electroblob.wizardry.spell;
|
package electroblob.wizardry.spell;
|
||||||
|
|
||||||
|
import electroblob.wizardry.Wizardry;
|
||||||
import electroblob.wizardry.registry.WizardryItems;
|
import electroblob.wizardry.registry.WizardryItems;
|
||||||
import electroblob.wizardry.util.RayTracer;
|
import electroblob.wizardry.util.RayTracer;
|
||||||
import electroblob.wizardry.util.SpellModifiers;
|
import electroblob.wizardry.util.SpellModifiers;
|
||||||
@@ -41,9 +42,8 @@ public class Blink extends Spell {
|
|||||||
world.spawnParticle(EnumParticleTypes.PORTAL, dx, dy, dz, world.rand.nextDouble() - 0.5,
|
world.spawnParticle(EnumParticleTypes.PORTAL, dx, dy, dz, world.rand.nextDouble() - 0.5,
|
||||||
world.rand.nextDouble() - 0.5, 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!
|
Wizardry.proxy.playBlinkEffect(caster);
|
||||||
electroblob.wizardry.client.WizardryClientEventHandler.playBlinkEffect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){
|
if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){
|
||||||
@@ -136,7 +136,7 @@ public class Blink extends Spell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canBeCastByNPCs(){
|
public boolean canBeCastBy(EntityLiving npc, boolean override){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import electroblob.wizardry.registry.WizardryItems;
|
|||||||
import electroblob.wizardry.util.ParticleBuilder;
|
import electroblob.wizardry.util.ParticleBuilder;
|
||||||
import electroblob.wizardry.util.ParticleBuilder.Type;
|
import electroblob.wizardry.util.ParticleBuilder.Type;
|
||||||
import electroblob.wizardry.util.SpellModifiers;
|
import electroblob.wizardry.util.SpellModifiers;
|
||||||
|
import net.minecraft.entity.EntityLiving;
|
||||||
import net.minecraft.entity.SharedMonsterAttributes;
|
import net.minecraft.entity.SharedMonsterAttributes;
|
||||||
import net.minecraft.entity.monster.EntityZombie;
|
import net.minecraft.entity.monster.EntityZombie;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
@@ -21,6 +22,7 @@ import net.minecraft.item.ItemStack;
|
|||||||
import net.minecraft.pathfinding.Path;
|
import net.minecraft.pathfinding.Path;
|
||||||
import net.minecraft.pathfinding.PathNodeType;
|
import net.minecraft.pathfinding.PathNodeType;
|
||||||
import net.minecraft.pathfinding.PathPoint;
|
import net.minecraft.pathfinding.PathPoint;
|
||||||
|
import net.minecraft.tileentity.TileEntityDispenser;
|
||||||
import net.minecraft.util.EnumHand;
|
import net.minecraft.util.EnumHand;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.text.TextComponentTranslation;
|
import net.minecraft.util.text.TextComponentTranslation;
|
||||||
@@ -44,8 +46,8 @@ public class Clairvoyance extends Spell {
|
|||||||
WizardData.registerStoredVariables(LOCATION_KEY, DIMENSION_KEY);
|
WizardData.registerStoredVariables(LOCATION_KEY, DIMENSION_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean canBeCastByNPCs() { return false; }
|
@Override public boolean canBeCastBy(EntityLiving npc, boolean override) { return false; }
|
||||||
@Override public boolean canBeCastByDispensers() { return false; }
|
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return false; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package electroblob.wizardry.spell;
|
|||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import electroblob.wizardry.item.IConjuredItem;
|
import electroblob.wizardry.item.IConjuredItem;
|
||||||
import electroblob.wizardry.registry.WizardryItems;
|
import electroblob.wizardry.registry.WizardryItems;
|
||||||
|
import electroblob.wizardry.util.NBTExtras;
|
||||||
import electroblob.wizardry.util.SpellModifiers;
|
import electroblob.wizardry.util.SpellModifiers;
|
||||||
import electroblob.wizardry.util.WizardryUtilities;
|
import electroblob.wizardry.util.WizardryUtilities;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
@@ -40,7 +41,7 @@ public class ConjureArmour extends SpellConjuration {
|
|||||||
armour = new ItemStack(SPECTRAL_ARMOUR_MAP.get(slot));
|
armour = new ItemStack(SPECTRAL_ARMOUR_MAP.get(slot));
|
||||||
IConjuredItem.setDurationMultiplier(armour, modifiers.get(WizardryItems.duration_upgrade));
|
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
|
// Sets a blank "ench" tag to trick the renderer into showing the enchantment effect on the armour model
|
||||||
armour.getTagCompound().setTag("ench", new NBTTagList());
|
NBTExtras.storeTagSafely(armour.getTagCompound(), "ench", new NBTTagList());
|
||||||
caster.setItemStackToSlot(slot, armour);
|
caster.setItemStackToSlot(slot, armour);
|
||||||
flag = true;
|
flag = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,12 +9,14 @@ import electroblob.wizardry.registry.WizardrySounds;
|
|||||||
import electroblob.wizardry.util.*;
|
import electroblob.wizardry.util.*;
|
||||||
import electroblob.wizardry.util.ParticleBuilder.Type;
|
import electroblob.wizardry.util.ParticleBuilder.Type;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityLiving;
|
||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.item.EnumAction;
|
import net.minecraft.item.EnumAction;
|
||||||
import net.minecraft.nbt.NBTTagList;
|
import net.minecraft.nbt.NBTTagList;
|
||||||
import net.minecraft.nbt.NBTUtil;
|
import net.minecraft.nbt.NBTUtil;
|
||||||
import net.minecraft.potion.PotionEffect;
|
import net.minecraft.potion.PotionEffect;
|
||||||
|
import net.minecraft.tileentity.TileEntityDispenser;
|
||||||
import net.minecraft.util.DamageSource;
|
import net.minecraft.util.DamageSource;
|
||||||
import net.minecraft.util.EnumFacing;
|
import net.minecraft.util.EnumFacing;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
@@ -45,9 +47,9 @@ public class CurseOfSoulbinding extends SpellRay {
|
|||||||
WizardData.registerStoredVariables(TARGETS_KEY);
|
WizardData.registerStoredVariables(TARGETS_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean canBeCastByNPCs() { return false; }
|
@Override public boolean canBeCastBy(EntityLiving npc, boolean override) { return false; }
|
||||||
// You can't damage a dispenser so this would be nonsense!
|
// You can't damage a dispenser so this would be nonsense!
|
||||||
@Override public boolean canBeCastByDispensers() { return false; }
|
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return false; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){
|
protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class Decoy extends Spell {
|
|||||||
addProperties(DECOY_LIFETIME, MOB_TRICK_CHANCE);
|
addProperties(DECOY_LIFETIME, MOB_TRICK_CHANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean canBeCastByNPCs(){ return true; }
|
@Override public boolean canBeCastBy(EntityLiving npc, boolean override){ return true; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ public class DragonFireball extends Spell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canBeCastByNPCs(){
|
public boolean canBeCastBy(EntityLiving npc, boolean override){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package electroblob.wizardry.spell;
|
package electroblob.wizardry.spell;
|
||||||
|
|
||||||
|
import electroblob.wizardry.Wizardry;
|
||||||
import electroblob.wizardry.constants.Constants;
|
import electroblob.wizardry.constants.Constants;
|
||||||
import electroblob.wizardry.event.SpellCastEvent;
|
import electroblob.wizardry.event.SpellCastEvent;
|
||||||
import electroblob.wizardry.registry.WizardryItems;
|
import electroblob.wizardry.registry.WizardryItems;
|
||||||
@@ -66,10 +67,16 @@ public class EmpoweringPresence extends Spell {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTranslationKey(){
|
||||||
|
return Wizardry.tisTheSeason ? super.getTranslationKey() + "_festive" : super.getTranslationKey();
|
||||||
|
}
|
||||||
|
|
||||||
@SubscribeEvent(priority = EventPriority.LOW) // Doesn't really matter but there's no point processing it if casting is blocked
|
@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){
|
public static void onSpellCastPreEvent(SpellCastEvent.Pre event){
|
||||||
// Empowerment stacks extra potency on top of the existing potency.
|
// Empowerment stacks extra potency on top of the existing potency.
|
||||||
if(event.getCaster() != null && event.getCaster().isPotionActive(WizardryPotions.empowerment)){
|
if(event.getCaster() != null && event.getCaster().isPotionActive(WizardryPotions.empowerment)
|
||||||
|
&& !(event.getSpell() instanceof EmpoweringPresence)){ // Prevent exponential empowerment stacking!
|
||||||
|
|
||||||
float potency = 1 + Constants.EMPOWERMENT_POTENCY_PER_LEVEL
|
float potency = 1 + Constants.EMPOWERMENT_POTENCY_PER_LEVEL
|
||||||
* (event.getCaster().getActivePotionEffect(WizardryPotions.empowerment).getAmplifier() + 1);
|
* (event.getCaster().getActivePotionEffect(WizardryPotions.empowerment).getAmplifier() + 1);
|
||||||
@@ -78,4 +85,5 @@ public class EmpoweringPresence extends Spell {
|
|||||||
event.getModifiers().get(SpellModifiers.POTENCY) * potency, true);
|
event.getModifiers().get(SpellModifiers.POTENCY) * potency, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -11,6 +11,7 @@ import net.minecraft.entity.EntityLivingBase;
|
|||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.item.EnumAction;
|
import net.minecraft.item.EnumAction;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.tileentity.TileEntityDispenser;
|
||||||
import net.minecraft.util.EnumFacing;
|
import net.minecraft.util.EnumFacing;
|
||||||
import net.minecraft.util.EnumHand;
|
import net.minecraft.util.EnumHand;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
@@ -29,8 +30,8 @@ public class ForestOfThorns extends Spell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean requiresPacket(){ return false; }
|
@Override public boolean requiresPacket(){ return false; }
|
||||||
@Override public boolean canBeCastByNPCs(){ return true; }
|
@Override public boolean canBeCastBy(EntityLiving npc, boolean override){ return true; }
|
||||||
@Override public boolean canBeCastByDispensers(){ return true; }
|
@Override public boolean canBeCastBy(TileEntityDispenser dispenser){ return true; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ public class FrostAxe extends SpellConjuration {
|
|||||||
|
|
||||||
public FrostAxe(){
|
public FrostAxe(){
|
||||||
super("frost_axe", WizardryItems.frost_axe);
|
super("frost_axe", WizardryItems.frost_axe);
|
||||||
|
addProperties(DAMAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import net.minecraft.entity.EntityLivingBase;
|
|||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.item.EnumAction;
|
import net.minecraft.item.EnumAction;
|
||||||
import net.minecraft.util.EnumHand;
|
import net.minecraft.util.EnumHand;
|
||||||
import net.minecraft.util.SoundEvent;
|
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class Glide extends Spell {
|
public class Glide extends Spell {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import net.minecraft.entity.player.EntityPlayer;
|
|||||||
import net.minecraft.entity.player.EntityPlayerMP;
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
import net.minecraft.item.EnumAction;
|
import net.minecraft.item.EnumAction;
|
||||||
import net.minecraft.network.play.server.SPacketEntityVelocity;
|
import net.minecraft.network.play.server.SPacketEntityVelocity;
|
||||||
|
import net.minecraft.tileentity.TileEntityDispenser;
|
||||||
import net.minecraft.util.EnumFacing;
|
import net.minecraft.util.EnumFacing;
|
||||||
import net.minecraft.util.EnumHand;
|
import net.minecraft.util.EnumHand;
|
||||||
import net.minecraft.util.SoundEvent;
|
import net.minecraft.util.SoundEvent;
|
||||||
@@ -58,12 +59,12 @@ public class Grapple extends Spell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canBeCastByNPCs(){
|
public boolean canBeCastBy(EntityLiving npc, boolean override){
|
||||||
return super.canBeCastByNPCs();
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canBeCastByDispensers(){
|
public boolean canBeCastBy(TileEntityDispenser dispenser){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,12 +9,14 @@ import electroblob.wizardry.util.ParticleBuilder.Type;
|
|||||||
import electroblob.wizardry.util.SpellModifiers;
|
import electroblob.wizardry.util.SpellModifiers;
|
||||||
import electroblob.wizardry.util.WizardryUtilities;
|
import electroblob.wizardry.util.WizardryUtilities;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityLiving;
|
||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.entity.item.EntityTNTPrimed;
|
import net.minecraft.entity.item.EntityTNTPrimed;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.entity.player.EntityPlayerMP;
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
import net.minecraft.item.EnumAction;
|
import net.minecraft.item.EnumAction;
|
||||||
import net.minecraft.network.play.server.SPacketEntityVelocity;
|
import net.minecraft.network.play.server.SPacketEntityVelocity;
|
||||||
|
import net.minecraft.tileentity.TileEntityDispenser;
|
||||||
import net.minecraft.util.EnumFacing;
|
import net.minecraft.util.EnumFacing;
|
||||||
import net.minecraft.util.SoundEvent;
|
import net.minecraft.util.SoundEvent;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
@@ -41,8 +43,8 @@ public class GreaterTelekinesis extends SpellRay {
|
|||||||
this.soundValues(0.8f, 1, 0.2f);
|
this.soundValues(0.8f, 1, 0.2f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean canBeCastByNPCs() { return false; }
|
@Override public boolean canBeCastBy(EntityLiving npc, boolean override) { return false; }
|
||||||
@Override public boolean canBeCastByDispensers() { return false; }
|
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return false; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected SoundEvent[] createSounds(){
|
protected SoundEvent[] createSounds(){
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package electroblob.wizardry.spell;
|
package electroblob.wizardry.spell;
|
||||||
|
|
||||||
|
import electroblob.wizardry.Wizardry;
|
||||||
import electroblob.wizardry.registry.WizardryItems;
|
import electroblob.wizardry.registry.WizardryItems;
|
||||||
import electroblob.wizardry.util.AllyDesignationSystem;
|
import electroblob.wizardry.util.AllyDesignationSystem;
|
||||||
import electroblob.wizardry.util.ParticleBuilder;
|
import electroblob.wizardry.util.ParticleBuilder;
|
||||||
@@ -62,4 +63,9 @@ public class InvigoratingPresence extends Spell {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getTranslationKey(){
|
||||||
|
return Wizardry.tisTheSeason ? super.getTranslationKey() + "_festive" : super.getTranslationKey();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import electroblob.wizardry.util.ParticleBuilder.Type;
|
|||||||
import electroblob.wizardry.util.SpellModifiers;
|
import electroblob.wizardry.util.SpellModifiers;
|
||||||
import electroblob.wizardry.util.WizardryUtilities;
|
import electroblob.wizardry.util.WizardryUtilities;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityLiving;
|
||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.entity.monster.*;
|
import net.minecraft.entity.monster.*;
|
||||||
import net.minecraft.entity.passive.*;
|
import net.minecraft.entity.passive.*;
|
||||||
@@ -52,7 +53,7 @@ public class Metamorphosis extends SpellRay {
|
|||||||
this.soundValues(0.5f, 1f, 0);
|
this.soundValues(0.5f, 1f, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean canBeCastByNPCs() { return false; }
|
@Override public boolean canBeCastBy(EntityLiving npc, boolean override) { return false; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){
|
protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import net.minecraft.item.EnumAction;
|
|||||||
import net.minecraft.item.EnumDyeColor;
|
import net.minecraft.item.EnumDyeColor;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
import net.minecraft.potion.PotionEffect;
|
import net.minecraft.potion.PotionEffect;
|
||||||
|
import net.minecraft.tileentity.TileEntityDispenser;
|
||||||
import net.minecraft.util.EnumFacing;
|
import net.minecraft.util.EnumFacing;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
@@ -43,8 +44,8 @@ public class MindControl extends SpellRay {
|
|||||||
addProperties(EFFECT_DURATION);
|
addProperties(EFFECT_DURATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean canBeCastByNPCs() { return false; }
|
@Override public boolean canBeCastBy(EntityLiving npc, boolean override) { return false; }
|
||||||
@Override public boolean canBeCastByDispensers() { return false; }
|
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return false; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){
|
protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){
|
||||||
|
|||||||
@@ -43,8 +43,7 @@ public class PhaseStep extends Spell {
|
|||||||
world.rand.nextDouble() - 0.5, 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!
|
Wizardry.proxy.playBlinkEffect(caster);
|
||||||
electroblob.wizardry.client.WizardryClientEventHandler.playBlinkEffect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){
|
if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import electroblob.wizardry.util.ParticleBuilder.Type;
|
|||||||
import electroblob.wizardry.util.SpellModifiers;
|
import electroblob.wizardry.util.SpellModifiers;
|
||||||
import electroblob.wizardry.util.WizardryUtilities;
|
import electroblob.wizardry.util.WizardryUtilities;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityLiving;
|
||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.init.MobEffects;
|
import net.minecraft.init.MobEffects;
|
||||||
@@ -28,7 +29,7 @@ public class Poison extends SpellRay {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canBeCastByNPCs(){
|
public boolean canBeCastBy(EntityLiving npc, boolean override){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import electroblob.wizardry.packet.PacketPossession;
|
|||||||
import electroblob.wizardry.packet.WizardryPacketHandler;
|
import electroblob.wizardry.packet.WizardryPacketHandler;
|
||||||
import electroblob.wizardry.registry.Spells;
|
import electroblob.wizardry.registry.Spells;
|
||||||
import electroblob.wizardry.registry.WizardryItems;
|
import electroblob.wizardry.registry.WizardryItems;
|
||||||
|
import electroblob.wizardry.util.NBTExtras;
|
||||||
import electroblob.wizardry.util.ParticleBuilder;
|
import electroblob.wizardry.util.ParticleBuilder;
|
||||||
import electroblob.wizardry.util.ParticleBuilder.Type;
|
import electroblob.wizardry.util.ParticleBuilder.Type;
|
||||||
import electroblob.wizardry.util.SpellModifiers;
|
import electroblob.wizardry.util.SpellModifiers;
|
||||||
@@ -43,6 +44,7 @@ import net.minecraft.item.ItemStack;
|
|||||||
import net.minecraft.nbt.NBTTagList;
|
import net.minecraft.nbt.NBTTagList;
|
||||||
import net.minecraft.potion.PotionEffect;
|
import net.minecraft.potion.PotionEffect;
|
||||||
import net.minecraft.potion.PotionUtils;
|
import net.minecraft.potion.PotionUtils;
|
||||||
|
import net.minecraft.tileentity.TileEntityDispenser;
|
||||||
import net.minecraft.util.*;
|
import net.minecraft.util.*;
|
||||||
import net.minecraft.util.math.AxisAlignedBB;
|
import net.minecraft.util.math.AxisAlignedBB;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
@@ -123,8 +125,8 @@ public class Possession extends SpellRay {
|
|||||||
addProperties(EFFECT_DURATION, CRITICAL_HEALTH);
|
addProperties(EFFECT_DURATION, CRITICAL_HEALTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean canBeCastByNPCs() { return false; }
|
@Override public boolean canBeCastBy(EntityLiving npc, boolean override) { return false; }
|
||||||
@Override public boolean canBeCastByDispensers() { return false; }
|
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return false; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean requiresPacket(){
|
public boolean requiresPacket(){
|
||||||
@@ -267,7 +269,7 @@ public class Possession extends SpellRay {
|
|||||||
// Inventory and items
|
// Inventory and items
|
||||||
|
|
||||||
if(possessor.getEntityData() != null){
|
if(possessor.getEntityData() != null){
|
||||||
possessor.getEntityData().setTag(INVENTORY_NBT_KEY, possessor.inventory.writeToNBT(new NBTTagList()));
|
NBTExtras.storeTagSafely(possessor.getEntityData(), INVENTORY_NBT_KEY, possessor.inventory.writeToNBT(new NBTTagList()));
|
||||||
}
|
}
|
||||||
|
|
||||||
possessor.inventory.clear();
|
possessor.inventory.clear();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package electroblob.wizardry.spell;
|
package electroblob.wizardry.spell;
|
||||||
|
|
||||||
import electroblob.wizardry.util.SpellModifiers;
|
import electroblob.wizardry.util.SpellModifiers;
|
||||||
|
import net.minecraft.entity.EntityLiving;
|
||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.util.EnumHand;
|
import net.minecraft.util.EnumHand;
|
||||||
@@ -17,7 +18,7 @@ public class ReplenishHunger extends SpellBuff {
|
|||||||
addProperties(HUNGER_POINTS, SATURATION_MODIFIER);
|
addProperties(HUNGER_POINTS, SATURATION_MODIFIER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean canBeCastByNPCs(){ return false; }
|
@Override public boolean canBeCastBy(EntityLiving npc, boolean override){ return false; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean applyEffects(EntityLivingBase caster, SpellModifiers modifiers){
|
protected boolean applyEffects(EntityLivingBase caster, SpellModifiers modifiers){
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ public class Resurrection extends Spell {
|
|||||||
|
|
||||||
public static final String WAIT_TIME = "wait_time";
|
public static final String WAIT_TIME = "wait_time";
|
||||||
|
|
||||||
|
private static final String POTION_CORE_FIX_NBT_KEY = "Potion Core - Health Fix";
|
||||||
|
|
||||||
public Resurrection(){
|
public Resurrection(){
|
||||||
super("resurrection", EnumAction.NONE, false);
|
super("resurrection", EnumAction.NONE, false);
|
||||||
addProperties(EFFECT_RADIUS, WAIT_TIME);
|
addProperties(EFFECT_RADIUS, WAIT_TIME);
|
||||||
@@ -90,6 +92,8 @@ public class Resurrection extends Spell {
|
|||||||
player.experience = 0;
|
player.experience = 0;
|
||||||
player.experienceLevel = 0;
|
player.experienceLevel = 0;
|
||||||
player.experienceTotal = 0;
|
player.experienceTotal = 0;
|
||||||
|
// Not sure what potion core is 'fixing' but it breaks my resurrection, so let's unfix it!
|
||||||
|
player.getEntityData().removeTag(POTION_CORE_FIX_NBT_KEY);
|
||||||
|
|
||||||
if(player.world.isRemote){
|
if(player.world.isRemote){
|
||||||
ParticleBuilder.spawnHealParticles(player.world, player);
|
ParticleBuilder.spawnHealParticles(player.world, player);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import net.minecraft.entity.Entity;
|
|||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.item.EnumAction;
|
import net.minecraft.item.EnumAction;
|
||||||
import net.minecraft.potion.PotionEffect;
|
import net.minecraft.potion.PotionEffect;
|
||||||
|
import net.minecraft.tileentity.TileEntityDispenser;
|
||||||
import net.minecraft.util.EnumFacing;
|
import net.minecraft.util.EnumFacing;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
@@ -28,7 +29,7 @@ public class Reversal extends SpellRay {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canBeCastByDispensers(){
|
public boolean canBeCastBy(TileEntityDispenser dispenser){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package electroblob.wizardry.spell;
|
package electroblob.wizardry.spell;
|
||||||
|
|
||||||
import electroblob.wizardry.util.SpellModifiers;
|
import electroblob.wizardry.util.SpellModifiers;
|
||||||
|
import net.minecraft.entity.EntityLiving;
|
||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.util.EnumHand;
|
import net.minecraft.util.EnumHand;
|
||||||
@@ -17,7 +18,7 @@ public class Satiety extends SpellBuff {
|
|||||||
addProperties(HUNGER_POINTS, SATURATION_MODIFIER);
|
addProperties(HUNGER_POINTS, SATURATION_MODIFIER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean canBeCastByNPCs(){ return false; }
|
@Override public boolean canBeCastBy(EntityLiving npc, boolean override){ return false; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean applyEffects(EntityLivingBase caster, SpellModifiers modifiers){
|
protected boolean applyEffects(EntityLivingBase caster, SpellModifiers modifiers){
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package electroblob.wizardry.spell;
|
package electroblob.wizardry.spell;
|
||||||
|
|
||||||
import electroblob.wizardry.registry.WizardryItems;
|
import electroblob.wizardry.registry.WizardryItems;
|
||||||
|
import electroblob.wizardry.util.NBTExtras;
|
||||||
import electroblob.wizardry.util.SpellModifiers;
|
import electroblob.wizardry.util.SpellModifiers;
|
||||||
import electroblob.wizardry.util.WizardryUtilities;
|
import electroblob.wizardry.util.WizardryUtilities;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
@@ -12,6 +13,7 @@ import net.minecraft.entity.projectile.EntityShulkerBullet;
|
|||||||
import net.minecraft.item.EnumAction;
|
import net.minecraft.item.EnumAction;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
import net.minecraft.nbt.NBTUtil;
|
import net.minecraft.nbt.NBTUtil;
|
||||||
|
import net.minecraft.tileentity.TileEntityDispenser;
|
||||||
import net.minecraft.util.EnumFacing;
|
import net.minecraft.util.EnumFacing;
|
||||||
import net.minecraft.util.EnumHand;
|
import net.minecraft.util.EnumHand;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
@@ -29,9 +31,9 @@ public class ShulkerBullet extends Spell {
|
|||||||
addProperties(RANGE);
|
addProperties(RANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean canBeCastByNPCs(){ return true; }
|
@Override public boolean canBeCastBy(EntityLiving npc, boolean override){ return true; }
|
||||||
|
|
||||||
@Override public boolean canBeCastByDispensers(){ return true; }
|
@Override public boolean canBeCastBy(TileEntityDispenser dispenser){ return true; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
||||||
@@ -89,7 +91,7 @@ public class ShulkerBullet extends Spell {
|
|||||||
targetTag.setInteger("X", pos.getX());
|
targetTag.setInteger("X", pos.getX());
|
||||||
targetTag.setInteger("Y", pos.getY());
|
targetTag.setInteger("Y", pos.getY());
|
||||||
targetTag.setInteger("Z", pos.getZ());
|
targetTag.setInteger("Z", pos.getZ());
|
||||||
nbt.setTag("Target", targetTag);
|
NBTExtras.storeTagSafely(nbt, "Target", targetTag);
|
||||||
bullet.readFromNBT(nbt); // LOL I just modified private fields without reflection
|
bullet.readFromNBT(nbt); // LOL I just modified private fields without reflection
|
||||||
|
|
||||||
world.spawnEntity(bullet);
|
world.spawnEntity(bullet);
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ package electroblob.wizardry.spell;
|
|||||||
import electroblob.wizardry.Wizardry;
|
import electroblob.wizardry.Wizardry;
|
||||||
import electroblob.wizardry.registry.WizardryPotions;
|
import electroblob.wizardry.registry.WizardryPotions;
|
||||||
import electroblob.wizardry.util.SpellModifiers;
|
import electroblob.wizardry.util.SpellModifiers;
|
||||||
|
import net.minecraft.entity.EntityLiving;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.tileentity.TileEntityDispenser;
|
||||||
import net.minecraft.util.EnumHand;
|
import net.minecraft.util.EnumHand;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
@@ -35,12 +37,12 @@ public class SlowTime extends SpellBuff {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canBeCastByDispensers(){
|
public boolean canBeCastBy(TileEntityDispenser dispenser){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canBeCastByNPCs(){
|
public boolean canBeCastBy(EntityLiving npc, boolean override){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,45 +0,0 @@
|
|||||||
package electroblob.wizardry.spell;
|
|
||||||
|
|
||||||
import electroblob.wizardry.registry.WizardryItems;
|
|
||||||
import electroblob.wizardry.util.SpellModifiers;
|
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
|
||||||
import net.minecraft.entity.projectile.EntitySnowball;
|
|
||||||
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", EnumAction.NONE, false);
|
|
||||||
addProperties(RANGE);
|
|
||||||
soundValues(0.5f, 0.4f, 0.2f);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean requiresPacket(){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
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, velocity, 1.0f);
|
|
||||||
world.spawnEntity(snowball);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.playSound(world, caster, ticksInUse, -1, modifiers);
|
|
||||||
caster.swingArm(hand);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -20,6 +20,7 @@ import net.minecraft.entity.player.EntityPlayer;
|
|||||||
import net.minecraft.entity.player.EntityPlayerMP;
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
import net.minecraft.item.EnumAction;
|
import net.minecraft.item.EnumAction;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
|
import net.minecraft.tileentity.TileEntityDispenser;
|
||||||
import net.minecraft.util.EnumFacing;
|
import net.minecraft.util.EnumFacing;
|
||||||
import net.minecraft.util.EnumHand;
|
import net.minecraft.util.EnumHand;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
@@ -42,6 +43,7 @@ import net.minecraftforge.registries.IForgeRegistryEntry;
|
|||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.function.BiPredicate;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@@ -149,6 +151,17 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
|
|||||||
/** The pitch variation of the sound played when this spell is cast. Defaults to 0. */
|
/** The pitch variation of the sound played when this spell is cast. Defaults to 0. */
|
||||||
protected float pitchVariation = 0;
|
protected float pitchVariation = 0;
|
||||||
|
|
||||||
|
// The following two fields are supposed to eliminate the need for boilerplate classes in spell packs.
|
||||||
|
// As an example, spells in the twilight forest spell pack only appear on custom spell book and scroll items and
|
||||||
|
// NPCs can only cast them if they spawned in the twilight forest. Without these convenience fields, spells that
|
||||||
|
// would not otherwise require their own classes have to have one just so they can override those two behaviours.
|
||||||
|
|
||||||
|
/** List of items for which this spell is applicable (used by default behaviour of {@link Spell#applicableForItem(Item)}). */
|
||||||
|
protected Item[] applicableItems;
|
||||||
|
/** Predicate that specifies a condition that NPCs must satisfy in order to spawn with this spell equipped (used by
|
||||||
|
* default behaviour of {@link Spell#canBeCastBy(EntityLiving, boolean)}). */
|
||||||
|
protected BiPredicate<EntityLiving, Boolean> npcSelector; // Kinda ugly but it's better than boilerplate classes
|
||||||
|
|
||||||
private static int nextSpellId = 0;
|
private static int nextSpellId = 0;
|
||||||
/** The spell's integer ID, mainly used for networking. */
|
/** 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...
|
// This was added after I learnt the hard way why you can't assume Forge's registry IDs are sequential...
|
||||||
@@ -186,6 +199,8 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
|
|||||||
this.icon = new ResourceLocation(modID, "textures/spells/" + name + ".png");
|
this.icon = new ResourceLocation(modID, "textures/spells/" + name + ".png");
|
||||||
this.sounds = createSounds();
|
this.sounds = createSounds();
|
||||||
this.id = nextSpellId++;
|
this.id = nextSpellId++;
|
||||||
|
this.items(WizardryItems.spell_book, WizardryItems.scroll);
|
||||||
|
this.npcSelector((e, o) -> canBeCastByNPCs()); // Fallback to old behaviour until we remove it entirely
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========================================= Initialisation methods ===========================================
|
// ========================================= Initialisation methods ===========================================
|
||||||
@@ -204,7 +219,7 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
|
|||||||
* @see Spell#playSound(World, double, double, double, int, int, SpellModifiers, String...)
|
* @see Spell#playSound(World, double, double, double, int, int, SpellModifiers, String...)
|
||||||
*/
|
*/
|
||||||
protected SoundEvent[] createSounds(){
|
protected SoundEvent[] createSounds(){
|
||||||
return new SoundEvent[]{WizardrySounds.createSound("spell." + this.getRegistryName().getPath())};
|
return new SoundEvent[]{WizardrySounds.createSound(this.getRegistryName().getNamespace(), "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
|
// Note 1: The aim here is conciseness. Keeping the identifiers in the spell classes means we don't usually have to
|
||||||
@@ -294,7 +309,7 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
|
|||||||
* @see Spell#createSoundsWithSuffixes(String[])
|
* @see Spell#createSoundsWithSuffixes(String[])
|
||||||
*/
|
*/
|
||||||
public final SoundEvent createSoundWithSuffix(String suffix){
|
public final SoundEvent createSoundWithSuffix(String suffix){
|
||||||
return WizardrySounds.createSound("spell." + this.getRegistryName().getPath() + "." + suffix);
|
return WizardrySounds.createSound(this.getRegistryName().getNamespace(), "spell." + this.getRegistryName().getPath() + "." + suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -354,7 +369,7 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
|
|||||||
* work if the caster is on full health).
|
* work if the caster is on full health).
|
||||||
* <p></p>
|
* <p></p>
|
||||||
* This method is intended for use by NPCs (see {@link EntityWizard}) so that they can cast spells. Override it if
|
* 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
|
* you want a spell to be cast by wizards. Note that you must also override {@link Spell#canBeCastBy(EntityLiving, boolean)} to
|
||||||
* return true to allow wizards to select the spell. For some spells, this method may well be exactly the same as
|
* 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 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.
|
* the player's look vector, but NPCs need to use a target-based method instead.
|
||||||
@@ -390,7 +405,7 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
|
|||||||
* won't work if the caster is on full health).
|
* won't work if the caster is on full health).
|
||||||
* <p></p>
|
* <p></p>
|
||||||
* This method is intended for use by dispensers and command blocks so that they can cast spells. Override it if
|
* 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
|
* you want a spell to be cast by dispensers. Note that you must also override {@link Spell#canBeCastBy(TileEntityDispenser)} to
|
||||||
* return true to allow dispensers to select the spell. For some spells, this method may well be exactly the same as
|
* 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 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.
|
* the player's look vector, but dispensers need to use a facing-based method instead.
|
||||||
@@ -446,20 +461,50 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
|
|||||||
public void finishCasting(World world, @Nullable EntityLivingBase caster, double x, double y, double z,
|
public void finishCasting(World world, @Nullable EntityLivingBase caster, double x, double y, double z,
|
||||||
@Nullable EnumFacing direction, int duration, SpellModifiers modifiers){}
|
@Nullable EnumFacing direction, int duration, SpellModifiers modifiers){}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the given entity can cast this spell. If you have overridden
|
||||||
|
* {@link Spell#cast(World, EntityLiving, EnumHand, int, EntityLivingBase, SpellModifiers)}, you should override
|
||||||
|
* this to return true (either always or under certain circumstances), or alternatively assign an NPC selector via
|
||||||
|
* {@link Spell#npcSelector(BiPredicate)} (recommended for general spell classes).
|
||||||
|
* @param npc The entity to query.
|
||||||
|
* @param override True if a player in creative mode is assigning this spell to the given entity, false otherwise.
|
||||||
|
* Usually this means situational conditions should be ignored.
|
||||||
|
*/
|
||||||
|
// We could make this final and force everyone to move over to the predicate system, but for particularly complex
|
||||||
|
// behaviour (i.e. several lines of code) it gets too ugly, and then you end up moving the contents of the predicate
|
||||||
|
// to a static method anyway and referring to it via method reference... so we may as well leave people the option.
|
||||||
|
public boolean canBeCastBy(EntityLiving npc, boolean override){
|
||||||
|
return npcSelector.test(npc, override);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether NPCs such as wizards can cast this spell. If you have overridden
|
* 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
|
* {@link Spell#cast(World, EntityLiving, EnumHand, int, EntityLivingBase, SpellModifiers)}, you should override
|
||||||
* this to return true.
|
* this to return true.
|
||||||
|
* @deprecated Use the entity-sensitive version {@link Spell#canBeCastBy(EntityLiving, boolean)}.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public boolean canBeCastByNPCs(){
|
public boolean canBeCastByNPCs(){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the given dispenser 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 (either always or under certain circumstances).
|
||||||
|
* @param dispenser The dispenser to query.
|
||||||
|
*/
|
||||||
|
public boolean canBeCastBy(TileEntityDispenser dispenser){
|
||||||
|
return canBeCastByDispensers();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether dispensers can cast this spell. If you have overridden
|
* 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
|
* {@link Spell#cast(World, double, double, double, EnumFacing, int, int, SpellModifiers)}, you should override this
|
||||||
* to return true.
|
* to return true.
|
||||||
|
* @deprecated Use the tileentity-sensitive version {@link Spell#canBeCastBy(TileEntityDispenser)}.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public boolean canBeCastByDispensers(){
|
public boolean canBeCastByDispensers(){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -561,26 +606,6 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
|
|||||||
return properties.getBaseValue(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 true if the given item has a variant for this spell. By default, returns true if the given item is
|
|
||||||
* either {@link WizardryItems#spell_book} or {@link WizardryItems#scroll}. Override to give the spell a special
|
|
||||||
* type of book or scroll. */
|
|
||||||
public boolean applicableForItem(Item item){
|
|
||||||
return item == WizardryItems.spell_book || item == WizardryItems.scroll;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the unlocalised name of the spell, without any prefixes or suffixes, e.g. "flame_ray". <b>This should
|
* Returns the unlocalised name of the spell, without any prefixes or suffixes, e.g. "flame_ray". <b>This should
|
||||||
* only be used for translation purposes.</b>
|
* only be used for translation purposes.</b>
|
||||||
@@ -597,13 +622,23 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
|
|||||||
* translating it. If, for whatever reason, you need to supply an ITextComponent but don't want it translated
|
* translating it. If, for whatever reason, you need to supply an ITextComponent but don't want it translated
|
||||||
* (perhaps a name?), you can use TextComponentString, which will simply keep the raw string it is given. */
|
* (perhaps a name?), you can use TextComponentString, which will simply keep the raw string it is given. */
|
||||||
|
|
||||||
|
/** Returns the translation key for this spell. */
|
||||||
|
protected String getTranslationKey(){
|
||||||
|
return "spell." + unlocalisedName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the translation key for this spell's description. */
|
||||||
|
protected String getDescriptionTranslationKey(){
|
||||||
|
return "spell." + unlocalisedName + ".desc";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the translated display name of the spell, without formatting (i.e. not coloured). <b>Client-side
|
* Returns the translated display name of the spell, without formatting (i.e. not coloured). <b>Client-side
|
||||||
* only!</b> On the server side, use {@link TextComponentTranslation} (see {@link Spell#getNameForTranslation()}).
|
* only!</b> On the server side, use {@link TextComponentTranslation} (see {@link Spell#getNameForTranslation()}).
|
||||||
*/
|
*/
|
||||||
@SideOnly(Side.CLIENT)
|
@SideOnly(Side.CLIENT)
|
||||||
public String getDisplayName(){
|
public String getDisplayName(){
|
||||||
return net.minecraft.client.resources.I18n.format("spell." + unlocalisedName);
|
return net.minecraft.client.resources.I18n.format(getTranslationKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -611,7 +646,7 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
|
|||||||
* formatting (i.e. not coloured).
|
* formatting (i.e. not coloured).
|
||||||
*/
|
*/
|
||||||
public ITextComponent getNameForTranslation(){
|
public ITextComponent getNameForTranslation(){
|
||||||
return new TextComponentTranslation("spell." + unlocalisedName);
|
return new TextComponentTranslation(getTranslationKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -620,7 +655,7 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
|
|||||||
*/
|
*/
|
||||||
@SideOnly(Side.CLIENT)
|
@SideOnly(Side.CLIENT)
|
||||||
public String getDisplayNameWithFormatting(){
|
public String getDisplayNameWithFormatting(){
|
||||||
return this.getElement().getFormattingCode() + net.minecraft.client.resources.I18n.format("spell." + unlocalisedName);
|
return this.getElement().getFormattingCode() + net.minecraft.client.resources.I18n.format(getTranslationKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -628,7 +663,7 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
|
|||||||
* formatting (i.e. coloured).
|
* formatting (i.e. coloured).
|
||||||
*/
|
*/
|
||||||
public ITextComponent getNameForTranslationFormatted(){
|
public ITextComponent getNameForTranslationFormatted(){
|
||||||
return new TextComponentTranslation("spell." + unlocalisedName).setStyle(this.getElement().getColour());
|
return new TextComponentTranslation(getTranslationKey()).setStyle(this.getElement().getColour());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -637,7 +672,7 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
|
|||||||
*/
|
*/
|
||||||
@SideOnly(Side.CLIENT)
|
@SideOnly(Side.CLIENT)
|
||||||
public String getDescription(){
|
public String getDescription(){
|
||||||
return net.minecraft.client.resources.I18n.format("spell." + unlocalisedName + ".desc");
|
return net.minecraft.client.resources.I18n.format(getDescriptionTranslationKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================ Sound methods ==============================================
|
// ============================================ Sound methods ==============================================
|
||||||
@@ -757,6 +792,51 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================= Misc methods ===============================================
|
||||||
|
|
||||||
|
/** 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 true if the given item has a variant for this spell. By default, returns true if the given item is
|
||||||
|
* in this spell's {@link Spell#applicableItems} list (set using {@link Spell#items(Item...)}). Override to do
|
||||||
|
* something more complex. */
|
||||||
|
public boolean applicableForItem(Item item){
|
||||||
|
return Arrays.asList(applicableItems).contains(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets which items this spell can appear on (these default to the regular spell book and scroll).
|
||||||
|
* @param applicableItems The items this spell should naturally appear on (or no items at all).
|
||||||
|
* @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 items(Item... applicableItems){
|
||||||
|
this.applicableItems = applicableItems;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies a condition that NPCs must satisfy in order to spawn with this spell equipped (this defaults to always
|
||||||
|
* true).
|
||||||
|
* @param selector A condition that NPCs must satisfy in order to spawn with this spell equipped.
|
||||||
|
* @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 npcSelector(BiPredicate<EntityLiving, Boolean> selector){
|
||||||
|
this.npcSelector = selector;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
// Spells are sorted according to tier and element. Where several spells have the same tier and element,
|
// Spells are sorted according to tier and element. Where several spells have the same tier and element,
|
||||||
// they will remain in the order they were registered.
|
// they will remain in the order they were registered.
|
||||||
@Override
|
@Override
|
||||||
@@ -775,7 +855,7 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the total number of registered spells, excluding the 'None' spell. Returns the same number that would be
|
* Returns the total number of registered spells, excluding the 'None' spell. Returns the same number that would be
|
||||||
* returned by {@code Spell.getSpells(Spell.allSpells).size()}, but this method is more efficient.
|
* returned by {@code Spell.getAllSpells().size()}, but this method is more efficient.
|
||||||
*/
|
*/
|
||||||
public static int getTotalSpellCount(){
|
public static int getTotalSpellCount(){
|
||||||
return registry.getValuesCollection().size() - 1;
|
return registry.getValuesCollection().size() - 1;
|
||||||
@@ -823,31 +903,37 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
|
|||||||
/**
|
/**
|
||||||
* Returns a list containing all spells matching the given {@link Predicate}. The returned list is separate from the
|
* Returns a list containing all spells matching the given {@link Predicate}. The returned list is separate from the
|
||||||
* internal spells list; any changes you make to the returned list will have no effect on wizardry since the
|
* 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
|
* returned list is local to this method. Never includes the {@link None} spell.
|
||||||
* predefined predicates in the Spell class (some of these really aren't shortcuts any more):
|
|
||||||
* <p></p>
|
|
||||||
* {@link Spell#allSpells} will allow all spells to be returned<br>
|
|
||||||
* {@link Spell#npcSpells} will only allow enabled spells that can be cast by NPCs (see
|
|
||||||
* {@link Spell#canBeCastByNPCs()})<br>
|
|
||||||
* {@link Spell#nonContinuousSpells} will filter out continuous spells but not disabled spells<br>
|
|
||||||
* {@link TierElementFilter} will only allow enabled spells of the specified tier and element
|
|
||||||
*
|
*
|
||||||
* @param filter A <code>Predicate<Spell></code> that the returned spells must satisfy.
|
* @param filter A <code>Predicate<Spell></code> that the returned spells must satisfy.
|
||||||
*
|
*
|
||||||
* @return A <b>local, modifiable</b> list of spells matching the given predicate. <i>Note that this list may be
|
* @return A <b>local, modifiable</b> list of spells matching the given predicate. <i>Note that this list may be
|
||||||
* empty.</i>
|
* empty.</i>
|
||||||
|
*
|
||||||
|
* @see TierElementFilter
|
||||||
*/
|
*/
|
||||||
public static List<Spell> getSpells(Predicate<Spell> filter){
|
public static List<Spell> getSpells(Predicate<Spell> filter){
|
||||||
return registry.getValuesCollection().stream().filter(filter.and(s -> s != Spells.none)).collect(Collectors.toList());
|
return registry.getValuesCollection().stream().filter(filter.and(s -> s != Spells.none)).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Predicate which allows all spells. */
|
/** Returns all registered spells, except the {@link None} spell. */
|
||||||
|
public static List<Spell> getAllSpells(){
|
||||||
|
return getSpells(s -> true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Predicate which allows all spells.
|
||||||
|
* @deprecated Use {@link Spell#getAllSpells()}. */
|
||||||
|
@Deprecated
|
||||||
public static Predicate<Spell> allSpells = s -> true;
|
public static Predicate<Spell> allSpells = s -> true;
|
||||||
|
|
||||||
/** Predicate which allows all non-continuous spells, even those that have been disabled. */
|
/** Predicate which allows all non-continuous spells, even those that have been disabled.
|
||||||
|
* @deprecated Nobody ever uses this now we have continuous scrolls, if you really need it just use a lambda. */
|
||||||
|
@Deprecated
|
||||||
public static Predicate<Spell> nonContinuousSpells = s -> !s.isContinuous;
|
public static Predicate<Spell> nonContinuousSpells = s -> !s.isContinuous;
|
||||||
|
|
||||||
/** Predicate which allows all enabled spells for which {@link Spell#canBeCastByNPCs()} returns true. */
|
/** Predicate which allows all enabled spells for which {@link Spell#canBeCastBy(EntityLiving, boolean)} returns true.
|
||||||
|
* @deprecated in favour of entity-sensitive version, use a lambda expression directly. */
|
||||||
|
@Deprecated
|
||||||
public static Predicate<Spell> npcSpells = s -> s.isEnabled(SpellProperties.Context.NPCS) && s.canBeCastByNPCs();
|
public static Predicate<Spell> npcSpells = s -> s.isEnabled(SpellProperties.Context.NPCS) && s.canBeCastByNPCs();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import net.minecraft.entity.EntityLiving;
|
|||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.item.EnumAction;
|
import net.minecraft.item.EnumAction;
|
||||||
|
import net.minecraft.tileentity.TileEntityDispenser;
|
||||||
import net.minecraft.util.EnumFacing;
|
import net.minecraft.util.EnumFacing;
|
||||||
import net.minecraft.util.EnumHand;
|
import net.minecraft.util.EnumHand;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
@@ -29,9 +30,9 @@ import java.util.function.Function;
|
|||||||
* <p></p>
|
* <p></p>
|
||||||
* Properties added by this type of spell: {@link Spell#RANGE}
|
* Properties added by this type of spell: {@link Spell#RANGE}
|
||||||
* <p></p>
|
* <p></p>
|
||||||
* By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastByNPCs()}
|
* By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastBy(EntityLiving, boolean)}
|
||||||
* <p></p>
|
* <p></p>
|
||||||
* By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastByDispensers()}
|
* By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastBy(TileEntityDispenser)}
|
||||||
* <p></p>
|
* <p></p>
|
||||||
* By default, this type of spell does not require a packet to be sent. {@link Spell#requiresPacket()}
|
* By default, this type of spell does not require a packet to be sent. {@link Spell#requiresPacket()}
|
||||||
*
|
*
|
||||||
@@ -58,13 +59,12 @@ public class SpellArrow<T extends EntityMagicArrow> extends Spell {
|
|||||||
super(modID, name, EnumAction.NONE, false);
|
super(modID, name, EnumAction.NONE, false);
|
||||||
this.arrowFactory = arrowFactory;
|
this.arrowFactory = arrowFactory;
|
||||||
this.addProperties(RANGE);
|
this.addProperties(RANGE);
|
||||||
|
this.npcSelector((e, o) -> true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean requiresPacket(){ return false; }
|
@Override public boolean requiresPacket(){ return false; }
|
||||||
|
|
||||||
@Override public boolean canBeCastByNPCs(){ return true; }
|
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return true; }
|
||||||
|
|
||||||
@Override public boolean canBeCastByDispensers() { return true; }
|
|
||||||
|
|
||||||
/** Computes the velocity the projectile should be launched at to achieve the required range. */
|
/** 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
|
// Long story short, it doesn't make much sense to me to have the JSON file specify the velocity - even less so if
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import net.minecraft.entity.player.EntityPlayer;
|
|||||||
import net.minecraft.item.EnumAction;
|
import net.minecraft.item.EnumAction;
|
||||||
import net.minecraft.potion.Potion;
|
import net.minecraft.potion.Potion;
|
||||||
import net.minecraft.potion.PotionEffect;
|
import net.minecraft.potion.PotionEffect;
|
||||||
|
import net.minecraft.tileentity.TileEntityDispenser;
|
||||||
import net.minecraft.util.EnumFacing;
|
import net.minecraft.util.EnumFacing;
|
||||||
import net.minecraft.util.EnumHand;
|
import net.minecraft.util.EnumHand;
|
||||||
import net.minecraft.util.math.AxisAlignedBB;
|
import net.minecraft.util.math.AxisAlignedBB;
|
||||||
@@ -32,9 +33,9 @@ import java.util.stream.Collectors;
|
|||||||
* <p></p>
|
* <p></p>
|
||||||
* Properties added by this type of spell: {@link SpellBuff#getDurationKey(Potion)}, {@link SpellBuff#getStrengthKey(Potion)}
|
* Properties added by this type of spell: {@link SpellBuff#getDurationKey(Potion)}, {@link SpellBuff#getStrengthKey(Potion)}
|
||||||
* <p></p>
|
* <p></p>
|
||||||
* By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastByNPCs()}
|
* By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastBy(EntityLiving, boolean)}
|
||||||
* <p></p>
|
* <p></p>
|
||||||
* By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastByDispensers()}
|
* By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastBy(TileEntityDispenser)}
|
||||||
* <p></p>
|
* <p></p>
|
||||||
* By default, this type of spell requires a packet to be sent. {@link Spell#requiresPacket()}
|
* By default, this type of spell requires a packet to be sent. {@link Spell#requiresPacket()}
|
||||||
*
|
*
|
||||||
@@ -67,6 +68,7 @@ public class SpellBuff extends Spell {
|
|||||||
this.r = r;
|
this.r = r;
|
||||||
this.g = g;
|
this.g = g;
|
||||||
this.b = b;
|
this.b = b;
|
||||||
|
this.npcSelector((e, o) -> true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -103,9 +105,7 @@ public class SpellBuff extends Spell {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean canBeCastByNPCs(){ return true; }
|
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return true; }
|
||||||
|
|
||||||
@Override public boolean canBeCastByDispensers() { return true; }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ import net.minecraft.world.World;
|
|||||||
* <p></p>
|
* <p></p>
|
||||||
* Properties added by this type of spell: {@link SpellConjuration#ITEM_LIFETIME}
|
* Properties added by this type of spell: {@link SpellConjuration#ITEM_LIFETIME}
|
||||||
* <p></p>
|
* <p></p>
|
||||||
* By default, this type of spell cannot be cast by NPCs. {@link Spell#canBeCastByNPCs()}
|
* By default, this type of spell cannot be cast by NPCs. {@link Spell#canBeCastBy(net.minecraft.entity.EntityLiving, boolean)}
|
||||||
* <p></p>
|
* <p></p>
|
||||||
* By default, this type of spell cannot be cast by dispensers. {@link Spell#canBeCastByDispensers()}
|
* By default, this type of spell cannot be cast by dispensers. {@link Spell#canBeCastBy(net.minecraft.tileentity.TileEntityDispenser)}
|
||||||
* <p></p>
|
* <p></p>
|
||||||
* By default, this type of spell requires a packet to be sent. {@link Spell#requiresPacket()}
|
* By default, this type of spell requires a packet to be sent. {@link Spell#requiresPacket()}
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import net.minecraft.entity.EntityLiving;
|
|||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.item.EnumAction;
|
import net.minecraft.item.EnumAction;
|
||||||
|
import net.minecraft.tileentity.TileEntityDispenser;
|
||||||
import net.minecraft.util.EnumFacing;
|
import net.minecraft.util.EnumFacing;
|
||||||
import net.minecraft.util.EnumHand;
|
import net.minecraft.util.EnumHand;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
@@ -29,9 +30,9 @@ import java.util.function.Function;
|
|||||||
* <p></p>
|
* <p></p>
|
||||||
* Properties added by this type of spell: {@link Spell#DURATION} (if the construct is not permanent)
|
* Properties added by this type of spell: {@link Spell#DURATION} (if the construct is not permanent)
|
||||||
* <p></p>
|
* <p></p>
|
||||||
* By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastByNPCs()}
|
* By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastBy(EntityLiving, boolean)}
|
||||||
* <p></p>
|
* <p></p>
|
||||||
* By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastByDispensers()}
|
* By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastBy(TileEntityDispenser)}
|
||||||
* <p></p>
|
* <p></p>
|
||||||
* By default, this type of spell does not require a packet to be sent. {@link Spell#requiresPacket()}
|
* By default, this type of spell does not require a packet to be sent. {@link Spell#requiresPacket()}
|
||||||
*
|
*
|
||||||
@@ -58,14 +59,13 @@ public class SpellConstruct<T extends EntityMagicConstruct> extends Spell {
|
|||||||
super(modID, name, action, false);
|
super(modID, name, action, false);
|
||||||
this.constructFactory = constructFactory;
|
this.constructFactory = constructFactory;
|
||||||
this.permanent = permanent;
|
this.permanent = permanent;
|
||||||
|
this.npcSelector((e, o) -> true);
|
||||||
if(!permanent) this.addProperties(DURATION);
|
if(!permanent) this.addProperties(DURATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean requiresPacket(){ return false; }
|
@Override public boolean requiresPacket(){ return false; }
|
||||||
|
|
||||||
@Override public boolean canBeCastByNPCs(){ return true; }
|
|
||||||
|
|
||||||
@Override public boolean canBeCastByDispensers() { return true; }
|
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return true; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets whether the construct must be spawned on the ground.
|
* Sets whether the construct must be spawned on the ground.
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import net.minecraft.entity.EntityLiving;
|
|||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.item.EnumAction;
|
import net.minecraft.item.EnumAction;
|
||||||
|
import net.minecraft.tileentity.TileEntityDispenser;
|
||||||
import net.minecraft.util.EnumFacing;
|
import net.minecraft.util.EnumFacing;
|
||||||
import net.minecraft.util.EnumHand;
|
import net.minecraft.util.EnumHand;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
@@ -30,9 +31,9 @@ import java.util.function.Function;
|
|||||||
* Properties added by this type of spell: {@link Spell#RANGE}, {@link Spell#DURATION} (if the construct is not
|
* Properties added by this type of spell: {@link Spell#RANGE}, {@link Spell#DURATION} (if the construct is not
|
||||||
* permanent)
|
* permanent)
|
||||||
* <p></p>
|
* <p></p>
|
||||||
* By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastByNPCs()}
|
* By default, this type of spell can be cast by NPCs. {@link Spell#canBeCastBy(EntityLiving, boolean)}
|
||||||
* <p></p>
|
* <p></p>
|
||||||
* By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastByDispensers()}
|
* By default, this type of spell can be cast by dispensers. {@link Spell#canBeCastBy(TileEntityDispenser)}
|
||||||
* <p></p>
|
* <p></p>
|
||||||
* By default, this type of spell does not require a packet to be sent. {@link Spell#requiresPacket()}
|
* By default, this type of spell does not require a packet to be sent. {@link Spell#requiresPacket()}
|
||||||
*
|
*
|
||||||
@@ -54,6 +55,7 @@ public class SpellConstructRanged<T extends EntityMagicConstruct> extends SpellC
|
|||||||
public SpellConstructRanged(String modID, String name, Function<World, T> constructFactory, boolean permanent){
|
public SpellConstructRanged(String modID, String name, Function<World, T> constructFactory, boolean permanent){
|
||||||
super(modID, name, EnumAction.NONE, constructFactory, permanent);
|
super(modID, name, EnumAction.NONE, constructFactory, permanent);
|
||||||
this.addProperties(RANGE);
|
this.addProperties(RANGE);
|
||||||
|
this.npcSelector((e, o) -> true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -79,10 +81,8 @@ public class SpellConstructRanged<T extends EntityMagicConstruct> extends SpellC
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean requiresPacket(){ return false; }
|
@Override public boolean requiresPacket(){ return false; }
|
||||||
|
|
||||||
@Override public boolean canBeCastByNPCs(){ return true; }
|
|
||||||
|
|
||||||
@Override public boolean canBeCastByDispensers() { return true; }
|
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return true; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user