Compare commits
101 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 | |||
| 01cea3df06 | |||
| 591cfb5857 | |||
| bc2037f74e | |||
| 6aa3b21190 | |||
| b262b6edc0 | |||
| b7be05669b | |||
| 071e299d48 | |||
| 1e885d70c3 | |||
| e04a43e56d | |||
| 378796cdda | |||
| 48c37d1c17 | |||
| fe8f9fc5cd | |||
| ced6ab7e8d | |||
| 378e02eb6c | |||
| 4677d9ff30 | |||
| 0541b2171b | |||
| dc59a14e82 | |||
| 1a13afb6e3 | |||
| 03dd76c18a | |||
| 9426a96df3 | |||
| 382faf59c9 | |||
| cab68e23ac | |||
| 60a6c5124e | |||
| 028b753be6 | |||
| d020668e0c | |||
| 656a78962e | |||
| 5a2f5aa295 | |||
| 5e37a2322c | |||
| 3ca9f200fd | |||
| 37e3a842f5 | |||
| 4e8e2c951b |
@@ -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]
|
||||
Wizardry version: 4.2.2 [change as necessary]
|
||||
Wizardry version: 4.2.8 [change 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.]
|
||||
|
||||
@@ -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]
|
||||
|
||||
|
||||
@@ -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]
|
||||
Wizardry version: 4.2.2 [change as necessary]
|
||||
Wizardry version: 4.2.8 [change as necessary]
|
||||
|
||||
Question details: [explain your question here]
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ run
|
||||
logs
|
||||
/misc
|
||||
/libs
|
||||
libs_src
|
||||
libsfordeobf
|
||||
generated
|
||||
Thumbs.db
|
||||
+10
-7
@@ -1,7 +1,7 @@
|
||||
# Credits
|
||||
|
||||
Electroblob's Wizardry
|
||||
Version 4.2.3
|
||||
Version 4.2.8
|
||||
For Minecraft 1.12.2
|
||||
|
||||
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
|
||||
- Avatair
|
||||
- Aeronica
|
||||
- UltraHex
|
||||
- Azim-Palmer
|
||||
- raoulvdberge
|
||||
|
||||
#### Translations
|
||||
|
||||
- Spanish and Mexican Spanish: MadWrist
|
||||
- Russian: VilagVil, kellixon
|
||||
- French: Hahdrim
|
||||
- Brazilian Portuguese: lorrampi
|
||||
- Chinese: ZHENGLOC, dragon-evol
|
||||
- Korean: shejery, rewi_wire
|
||||
- Spanish and Mexican Spanish: MadWrist
|
||||
- Russian: VilagVil, kellixon, bigenergy
|
||||
- French: Hahdrim
|
||||
- Brazilian Portuguese: lorrampi
|
||||
- Chinese: ZHENGLOC, dragon-evol
|
||||
- Korean: shejery, rewi_wire
|
||||
- Polish: Trozuu
|
||||
|
||||
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.
|
||||
|
||||
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]
|
||||
|
||||
Issue details: [describe what you were doing when the issue occurred, what went wrong, what you expected to happen, etc.]
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Wizardry [](https://minecraft.curseforge.com/projects/electroblobs-wizardry) [](https://minecraft.curseforge.com/projects/electroblobs-wizardry/files) [](https://minecraft.curseforge.com/projects/electroblobs-wizardry/relations/dependents) [](https://discord.gg/MTmMzMv)
|
||||
# Wizardry [](https://minecraft.curseforge.com/projects/electroblobs-wizardry) [](https://minecraft.curseforge.com/projects/electroblobs-wizardry/files) [](https://discord.gg/MTmMzMv)
|
||||
|
||||

|
||||

|
||||
|
||||
Source code for Electroblob's Wizardry, a Minecraft mod currently for versions 1.7.10, 1.10.2, 1.11.2, and 1.12.2. Wizardry adds an RPG-style system of magic spells to Minecraft with the aim of being as playable as possible. No crazy constructs, no perk trees, no complex recipes - simply find spell books, cast spells, and master the arcane!
|
||||
|
||||
Please read the [guide for contributing](guide_for_contributing.md) before submitting an issue or a PR.
|
||||
Please read the [guide for contributing](CONTRIBUTING.md) before submitting an issue or a PR.
|
||||
|
||||
<b>Links</b>
|
||||
|
||||
|
||||
+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.
|
||||
|
||||
|
||||
version = "4.2.3" // 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
|
||||
archivesBaseName = "ElectroblobsWizardry"
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import electroblob.wizardry.spell.Spell;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
@@ -99,9 +100,9 @@ public class CommonProxy {
|
||||
return ((ItemSpectralBow)WizardryItems.spectral_bow).getDefaultDurabilityForDisplay(stack);
|
||||
}
|
||||
|
||||
/** Like {@link CommonProxy#addMultiLineDescription(List, String, Style)}, but style defaults to light grey. */
|
||||
public void addMultiLineDescription(List<String> tooltip, String key){
|
||||
this.addMultiLineDescription(tooltip, key, new Style().setColor(TextFormatting.GRAY));
|
||||
/** Like {@link CommonProxy#addMultiLineDescription(List, String, Style, Object...)}, but style defaults to light grey. */
|
||||
public void addMultiLineDescription(List<String> tooltip, String key, Object... args){
|
||||
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 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
|
||||
// ===============================================================================================================
|
||||
@@ -139,8 +140,6 @@ public class CommonProxy {
|
||||
|
||||
public void handleAdvancementSyncPacket(PacketSyncAdvancements.Message message){}
|
||||
|
||||
public void handleEndSlowTimePacket(PacketEndSlowTime.Message message){}
|
||||
|
||||
public void handleResurrectionPacket(PacketResurrection.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!");
|
||||
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
|
||||
|
||||
@@ -17,6 +17,7 @@ import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
|
||||
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -168,6 +169,8 @@ public final class Settings {
|
||||
/** <b>[Server-only]</b> Whether to replace Minecraft's distance-based fall damage calculation with an equivalent,
|
||||
* velocity-based one. */
|
||||
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
|
||||
* to the defaults.
|
||||
@@ -364,7 +367,7 @@ public final class Settings {
|
||||
*/
|
||||
void initConfig(FMLPreInitializationEvent event){
|
||||
|
||||
config = new Configuration(event.getSuggestedConfigurationFile());
|
||||
config = new Configuration(new File(Wizardry.configDirectory, Wizardry.MODID + ".cfg"));
|
||||
config.load();
|
||||
|
||||
Wizardry.logger.info("Setting up main config");
|
||||
@@ -430,7 +433,7 @@ public final class Settings {
|
||||
|
||||
Property property;
|
||||
|
||||
for(Spell spell : Spell.getSpells(Spell.allSpells)){
|
||||
for(Spell spell : Spell.getAllSpells()){
|
||||
property = config.get(SPELLS_CATEGORY, spell.getRegistryName().toString(), true,
|
||||
I18n.translateToLocal("spell." + spell.getUnlocalisedName() + ".desc"));
|
||||
// Uses the same config key as the spell name, because - well, that's what it's called!
|
||||
@@ -541,6 +544,13 @@ public final class Settings {
|
||||
slowTimeAffectsPlayers = property.getBoolean();
|
||||
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.setLanguageKey("config." + Wizardry.MODID + ".mob_loot_table_whitelist");
|
||||
property.setRequiresMcRestart(true);
|
||||
@@ -700,7 +710,7 @@ public final class Settings {
|
||||
fastWorldgen = property.getBoolean();
|
||||
propOrder.add(property.getName());
|
||||
|
||||
property = config.get(WORLDGEN_CATEGORY, "towerDimensions", new int[]{0}, "List of dimension ids in which wizard towers will generate.");
|
||||
property = config.get(WORLDGEN_CATEGORY, "towerDimensions", new int[]{0}, "List of dimension ids in which wizard towers will generate. Remove all dimensions to disable wizard towers completely.");
|
||||
property.setLanguageKey("config." + Wizardry.MODID + ".tower_dimensions");
|
||||
property.setRequiresWorldRestart(true);
|
||||
towerDimensions = property.getIntList();
|
||||
@@ -725,20 +735,20 @@ public final class Settings {
|
||||
propOrder.add(property.getName());
|
||||
|
||||
property = config.get(WORLDGEN_CATEGORY, "towerFiles", new String[]{Wizardry.MODID + ":wizard_tower_0", Wizardry.MODID + ":wizard_tower_1", Wizardry.MODID + ":wizard_tower_2", Wizardry.MODID + ":wizard_tower_3"},
|
||||
"List of structure file locations for wizard towers without loot chests. One of these files will be randomly selected each time a wizard tower is generated. File locations are of the format [mod id]:[filename], which refers to the file assets/[mod id]/structures/[filename].nbt. Duplicate entries are permitted, allowing for simple weighting without duplicating the structure files themselves.");
|
||||
"List of structure file locations for wizard towers without loot chests. One of these files will be randomly selected each time a wizard tower is generated. File locations are of the format [mod id]:[filename], which refers to the file assets/[mod id]/structures/[filename].nbt. Duplicate entries are permitted, allowing for simple weighting without duplicating the structure files themselves. This list should not be empty; to disable wizard towers, use the tower dimensions setting.");
|
||||
property.setLanguageKey("config." + Wizardry.MODID + ".tower_files");
|
||||
property.setRequiresWorldRestart(true);
|
||||
towerFiles = getResourceLocationList(property);
|
||||
propOrder.add(property.getName());
|
||||
|
||||
property = config.get(WORLDGEN_CATEGORY, "towerWithChestFiles", new String[]{Wizardry.MODID + ":wizard_tower_chest_0", Wizardry.MODID + ":wizard_tower_chest_1", Wizardry.MODID + ":wizard_tower_chest_2", Wizardry.MODID + ":wizard_tower_chest_3"},
|
||||
"List of structure file locations for wizard towers with loot chests. One of these files will be randomly selected each time a wizard tower is generated. File locations are of the format [mod id]:[filename], which refers to the file assets/[mod id]/structures/[filename].nbt. Duplicate entries are permitted, allowing for simple weighting without duplicating the structure files themselves.");
|
||||
"List of structure file locations for wizard towers with loot chests. One of these files will be randomly selected each time a wizard tower is generated. File locations are of the format [mod id]:[filename], which refers to the file assets/[mod id]/structures/[filename].nbt. Duplicate entries are permitted, allowing for simple weighting without duplicating the structure files themselves. This list should not be empty; to disable wizard towers, use the tower dimensions setting.");
|
||||
property.setLanguageKey("config." + Wizardry.MODID + ".tower_with_chest_files");
|
||||
property.setRequiresWorldRestart(true);
|
||||
towerWithChestFiles = getResourceLocationList(property);
|
||||
propOrder.add(property.getName());
|
||||
|
||||
property = config.get(WORLDGEN_CATEGORY, "obeliskDimensions", new int[]{0, -1}, "List of dimension ids in which obelisks will generate.");
|
||||
property = config.get(WORLDGEN_CATEGORY, "obeliskDimensions", new int[]{0, -1}, "List of dimension ids in which obelisks will generate. Remove all dimensions to disable obelisks completely.");
|
||||
property.setLanguageKey("config." + Wizardry.MODID + ".obelisk_dimensions");
|
||||
property.setRequiresWorldRestart(true);
|
||||
obeliskDimensions = property.getIntList();
|
||||
@@ -752,13 +762,13 @@ public final class Settings {
|
||||
propOrder.add(property.getName());
|
||||
|
||||
property = config.get(WORLDGEN_CATEGORY, "obeliskFiles", new String[]{Wizardry.MODID + ":obelisk_0", Wizardry.MODID + ":obelisk_1", Wizardry.MODID + ":obelisk_2", Wizardry.MODID + ":obelisk_3", Wizardry.MODID + ":obelisk_4"},
|
||||
"List of structure file locations for obelisks. One of these files will be randomly selected each time an obelisk is generated. File locations are of the format [mod id]:[filename], which refers to the file assets/[mod id]/structures/[filename].nbt. Duplicate entries are permitted, allowing for simple weighting without duplicating the structure files themselves.");
|
||||
"List of structure file locations for obelisks. One of these files will be randomly selected each time an obelisk is generated. File locations are of the format [mod id]:[filename], which refers to the file assets/[mod id]/structures/[filename].nbt. Duplicate entries are permitted, allowing for simple weighting without duplicating the structure files themselves. This list should not be empty; to disable obelisks, use the obelisk dimensions setting.");
|
||||
property.setLanguageKey("config." + Wizardry.MODID + ".obelisk_files");
|
||||
property.setRequiresWorldRestart(true);
|
||||
obeliskFiles = getResourceLocationList(property);
|
||||
propOrder.add(property.getName());
|
||||
|
||||
property = config.get(WORLDGEN_CATEGORY, "shrineDimensions", new int[]{0, -1}, "List of dimension ids in which shrines will generate.");
|
||||
property = config.get(WORLDGEN_CATEGORY, "shrineDimensions", new int[]{0, -1}, "List of dimension ids in which shrines will generate. Remove all dimensions to disable shrines completely.");
|
||||
property.setLanguageKey("config." + Wizardry.MODID + ".shrine_dimensions");
|
||||
property.setRequiresWorldRestart(true);
|
||||
shrineDimensions = property.getIntList();
|
||||
@@ -772,7 +782,7 @@ public final class Settings {
|
||||
propOrder.add(property.getName());
|
||||
|
||||
property = config.get(WORLDGEN_CATEGORY, "shrineFiles", new String[]{Wizardry.MODID + ":shrine_0", Wizardry.MODID + ":shrine_1", Wizardry.MODID + ":shrine_2", Wizardry.MODID + ":shrine_3", Wizardry.MODID + ":shrine_4", Wizardry.MODID + ":shrine_5", Wizardry.MODID + ":shrine_6", Wizardry.MODID + ":shrine_7"},
|
||||
"List of structure file locations for shrines. One of these files will be randomly selected each time a shrine is generated. File locations are of the format [mod id]:[filename], which refers to the file assets/[mod id]/structures/[filename].nbt. Duplicate entries are permitted, allowing for simple weighting without duplicating the structure files themselves.");
|
||||
"List of structure file locations for shrines. One of these files will be randomly selected each time a shrine is generated. File locations are of the format [mod id]:[filename], which refers to the file assets/[mod id]/structures/[filename].nbt. Duplicate entries are permitted, allowing for simple weighting without duplicating the structure files themselves. This list should not be empty; to disable shrines, use the shrine dimensions setting.");
|
||||
property.setLanguageKey("config." + Wizardry.MODID + ".shrine_files");
|
||||
property.setRequiresWorldRestart(true);
|
||||
shrineFiles = getResourceLocationList(property);
|
||||
|
||||
@@ -31,6 +31,9 @@ import net.minecraftforge.fml.common.network.NetworkRegistry;
|
||||
import net.minecraftforge.fml.common.registry.GameRegistry;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
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
|
||||
* possible. No crazy constructs, no perk trees, no complex recipes - simply find spell books, cast spells, and master
|
||||
@@ -61,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.11.x versions, and so on.
|
||||
*/
|
||||
public static final String VERSION = "4.2.3";
|
||||
public static final String VERSION = "4.2.8";
|
||||
|
||||
// IDEA: Triggering of inbuilt Forge events in relevant places?
|
||||
// IDEA: Abstract the vanilla particles behind the particle builder
|
||||
@@ -82,6 +85,12 @@ public class Wizardry {
|
||||
* - <b>INFO</b>: Anything that might happen during normal mod operation that the user needs to know about. */
|
||||
public static Logger logger;
|
||||
|
||||
/** A {@link File} object representing wizardry's config folder, {@code config/ebwizardry}). As of wizardry 4.2.4,
|
||||
* this folder contains the main config file and the global spell properties folder, if used. */
|
||||
public static File configDirectory;
|
||||
|
||||
public static boolean tisTheSeason;
|
||||
|
||||
// The instance of wizardry that Forge uses.
|
||||
@Instance(Wizardry.MODID)
|
||||
public static Wizardry instance;
|
||||
@@ -97,8 +106,13 @@ public class Wizardry {
|
||||
|
||||
proxy.registerResourceReloadListeners();
|
||||
|
||||
configDirectory = new File(event.getModConfigurationDirectory(), Wizardry.MODID);
|
||||
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
|
||||
WizardData.register();
|
||||
DispenserCastingData.register();
|
||||
|
||||
@@ -33,6 +33,9 @@ import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.text.TextComponentTranslation;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraft.world.storage.loot.LootContext;
|
||||
import net.minecraft.world.storage.loot.LootTable;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.common.util.FakePlayer;
|
||||
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 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
|
||||
@@ -343,18 +347,21 @@ public final class WizardryEventHandler {
|
||||
|
||||
Spell spell = ((ISpellCaster)event.getEntity()).getContinuousSpell();
|
||||
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(!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.
|
||||
// Right now that doesn't matter because NPCs don't use modifiers, but they might in future
|
||||
((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();
|
||||
|
||||
// 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)){
|
||||
|
||||
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);
|
||||
// }
|
||||
|
||||
event.setDistance((float)y);
|
||||
// Don't let it increase fall damage beyond vanilla values
|
||||
if(y < event.getDistance()) event.setDistance((float)y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package electroblob.wizardry;
|
||||
|
||||
import electroblob.wizardry.item.ItemSpellBook;
|
||||
import electroblob.wizardry.item.ItemWizardHandbook;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import electroblob.wizardry.tileentity.ContainerArcaneWorkbench;
|
||||
import electroblob.wizardry.tileentity.ContainerPortableWorkbench;
|
||||
import electroblob.wizardry.tileentity.TileEntityArcaneWorkbench;
|
||||
@@ -48,9 +47,9 @@ public class WizardryGuiHandler implements IGuiHandler {
|
||||
return new electroblob.wizardry.client.gui.handbook.GuiWizardHandbook();
|
||||
}else if(id == SPELL_BOOK){
|
||||
if(player.getHeldItemMainhand().getItem() instanceof ItemSpellBook){
|
||||
return new electroblob.wizardry.client.gui.GuiSpellBook(Spell.byMetadata(player.getHeldItemMainhand().getItemDamage()));
|
||||
return new electroblob.wizardry.client.gui.GuiSpellBook(player.getHeldItemMainhand());
|
||||
}else if(player.getHeldItemOffhand().getItem() instanceof ItemSpellBook){
|
||||
return new electroblob.wizardry.client.gui.GuiSpellBook(Spell.byMetadata(player.getHeldItemOffhand().getItemDamage()));
|
||||
return new electroblob.wizardry.client.gui.GuiSpellBook(player.getHeldItemOffhand());
|
||||
}
|
||||
}else if(id == PORTABLE_CRAFTING){
|
||||
return new electroblob.wizardry.client.gui.GuiPortableCrafting(player.inventory, world, new BlockPos(x, y, z));
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package electroblob.wizardry.block;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.registry.WizardryBlocks;
|
||||
import electroblob.wizardry.util.ParticleBuilder;
|
||||
import electroblob.wizardry.util.ParticleBuilder.Type;
|
||||
@@ -56,7 +57,7 @@ public class BlockCrystalFlower extends BlockBush {
|
||||
@SubscribeEvent
|
||||
public static void onBonemealEvent(BonemealEvent event){
|
||||
// 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),
|
||||
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);
|
||||
else{
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ public class ClientProxy extends CommonProxy {
|
||||
// Armour Model
|
||||
public static final ModelBiped WIZARD_ARMOUR_MODEL = new ModelWizardArmour(0.75f);
|
||||
|
||||
/** The wrap width for standard multi-line descriptions (see {@link ClientProxy#addMultiLineDescription(List, String, Style)}). */
|
||||
/** The wrap width for standard multi-line descriptions (see {@link ClientProxy#addMultiLineDescription(List, String, Style, Object...)}). */
|
||||
private static final int TOOLTIP_WRAP_WIDTH = 140;
|
||||
|
||||
// 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
|
||||
public Set<String> getSpellHUDSkins(){
|
||||
return GuiSpellDisplay.getSkinKeys();
|
||||
@@ -282,8 +287,8 @@ public class ClientProxy extends CommonProxy {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMultiLineDescription(List<String> tooltip, String key, Style style){
|
||||
String description = style.getFormattingCode() + I18n.format(key);
|
||||
public void addMultiLineDescription(List<String> tooltip, String key, Style style, Object... args){
|
||||
String description = style.getFormattingCode() + I18n.format(key, args);
|
||||
tooltip.addAll(Minecraft.getMinecraft().fontRenderer.listFormattedStringToWidth(description, TOOLTIP_WRAP_WIDTH));
|
||||
}
|
||||
|
||||
@@ -429,6 +434,7 @@ public class ClientProxy extends CommonProxy {
|
||||
if(caster instanceof ISpellCaster){
|
||||
if(spell.isContinuous || spell instanceof None){
|
||||
((ISpellCaster)caster).setContinuousSpell(spell);
|
||||
((ISpellCaster)caster).setSpellCounter(spell instanceof None ? 0 : 1);
|
||||
((EntityLiving)caster).setAttackTarget((EntityLivingBase)target);
|
||||
}
|
||||
}
|
||||
@@ -542,7 +548,7 @@ public class ClientProxy extends CommonProxy {
|
||||
data.randomNames = 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
|
||||
// This is a case where we must use the network ID, not the metadata
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEndSlowTimePacket(PacketEndSlowTime.Message message){
|
||||
Entity entity = Minecraft.getMinecraft().world.getEntityByID(message.hostID);
|
||||
if(entity instanceof EntityLivingBase) PotionSlowTime.unblockNearbyEntities((EntityLivingBase)entity);
|
||||
else Wizardry.logger.warn("Received a PacketEndSlowTime, but the entity ID did not match any living entity");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleResurrectionPacket(PacketResurrection.Message message){
|
||||
Entity entity = Minecraft.getMinecraft().world.getEntityByID(message.playerID);
|
||||
|
||||
@@ -9,6 +9,7 @@ import electroblob.wizardry.data.WizardData;
|
||||
import electroblob.wizardry.item.ISpellCastingItem;
|
||||
import electroblob.wizardry.item.ItemArtefact;
|
||||
import electroblob.wizardry.item.ItemSpectralBow;
|
||||
import electroblob.wizardry.potion.PotionSlowTime;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardryItems;
|
||||
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.entity.RenderManager;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.client.settings.KeyBinding;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.SharedMonsterAttributes;
|
||||
import net.minecraft.entity.ai.attributes.AttributeModifier;
|
||||
import net.minecraft.entity.item.EntityArmorStand;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
@@ -35,18 +33,17 @@ import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityDispenser;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.village.MerchantRecipe;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.client.event.*;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import 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.
|
||||
@@ -71,12 +68,6 @@ public final class WizardryClientEventHandler {
|
||||
private static int blinkEffectTimer;
|
||||
/** The number of ticks the blink effect lasts for. */
|
||||
private static final int BLINK_EFFECT_DURATION = 8;
|
||||
|
||||
private static final Method unpressKey;
|
||||
|
||||
static {
|
||||
unpressKey = ObfuscationReflectionHelper.findMethod(KeyBinding.class, "func_74505_d", void.class);
|
||||
}
|
||||
|
||||
/** Starts the first person blink overlay effect. */
|
||||
public static void playBlinkEffect(){
|
||||
@@ -151,7 +142,10 @@ public final class WizardryClientEventHandler {
|
||||
|
||||
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(DispenserCastingData.get((TileEntityDispenser)tileentity) != null){
|
||||
DispenserCastingData.get((TileEntityDispenser)tileentity).update();
|
||||
@@ -160,6 +154,7 @@ public final class WizardryClientEventHandler {
|
||||
}
|
||||
|
||||
SpellEmitterData.update(world);
|
||||
PotionSlowTime.cleanUpEntities(world);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
import net.minecraftforge.client.event.TextureStitchEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package electroblob.wizardry.client.gui;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.client.DrawingUtils;
|
||||
import electroblob.wizardry.constants.Tier;
|
||||
import electroblob.wizardry.data.SpellGlyphData;
|
||||
import electroblob.wizardry.data.WizardData;
|
||||
import electroblob.wizardry.item.ItemSpellBook;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
@@ -14,27 +14,22 @@ import net.minecraft.client.audio.PositionedSoundRecord;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class GuiSpellBook extends GuiScreen {
|
||||
|
||||
private int xSize, ySize;
|
||||
private ItemSpellBook book;
|
||||
private Spell spell;
|
||||
|
||||
private static final Map<Tier, ResourceLocation> textures = ImmutableMap.of(
|
||||
Tier.NOVICE, new ResourceLocation(Wizardry.MODID, "textures/gui/spell_book_novice.png"),
|
||||
Tier.APPRENTICE, new ResourceLocation(Wizardry.MODID, "textures/gui/spell_book_apprentice.png"),
|
||||
Tier.ADVANCED, new ResourceLocation(Wizardry.MODID, "textures/gui/spell_book_advanced.png"),
|
||||
Tier.MASTER, new ResourceLocation(Wizardry.MODID, "textures/gui/spell_book_master.png"));
|
||||
|
||||
public GuiSpellBook(Spell spell){
|
||||
public GuiSpellBook(ItemStack stack){
|
||||
super();
|
||||
xSize = 288;
|
||||
ySize = 180;
|
||||
this.spell = spell;
|
||||
if(!(stack.getItem() instanceof ItemSpellBook)) throw new ClassCastException("Cannot create spell book GUI for item that does not extend ItemSpellBook!");
|
||||
this.book = (ItemSpellBook)stack.getItem();
|
||||
this.spell = Spell.byMetadata(stack.getItemDamage());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,7 +54,7 @@ public class GuiSpellBook extends GuiScreen {
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(discovered ? spell.getIcon() : Spells.none.getIcon());
|
||||
DrawingUtils.drawTexturedRect(xPos + 146, yPos + 20, 0, 0, 128, 128, 128, 128);
|
||||
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(textures.get(spell.getTier()));
|
||||
Minecraft.getMinecraft().renderEngine.bindTexture(book.getGuiTexture(spell));
|
||||
DrawingUtils.drawTexturedRect(xPos, yPos, 0, 0, xSize, ySize, xSize, 256);
|
||||
|
||||
super.drawScreen(par1, par2, par3);
|
||||
@@ -77,7 +72,7 @@ public class GuiSpellBook extends GuiScreen {
|
||||
//this.fontRenderer.drawString("-------------------", xPos + 17, yPos + 35, 0);
|
||||
|
||||
if(spell.getTier() == Tier.NOVICE){
|
||||
// Basic is usually white but this doesn't show up.
|
||||
// Novice is usually white but this doesn't show up.
|
||||
this.fontRenderer.drawString("Tier: \u00A77" + Tier.NOVICE.getDisplayName(), xPos + 17, yPos + 45, 0);
|
||||
}else{
|
||||
this.fontRenderer.drawString("Tier: " + spell.getTier().getDisplayNameWithFormatting(), xPos + 17, yPos + 45, 0);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package electroblob.wizardry.client.model;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.block.BlockStatue;
|
||||
import net.minecraft.client.model.ModelRenderer;
|
||||
import net.minecraft.entity.Entity;
|
||||
@@ -13,6 +14,7 @@ public class ModelWizardArmour extends ModelArmourFixer {
|
||||
ModelRenderer hatSegment4;
|
||||
ModelRenderer hatSegment5;
|
||||
ModelRenderer hatSegment6;
|
||||
ModelRenderer hatBobble;
|
||||
ModelRenderer robe;
|
||||
|
||||
public ModelWizardArmour(float delta){
|
||||
@@ -75,6 +77,13 @@ public class ModelWizardArmour extends ModelArmourFixer {
|
||||
hatSegment6.mirror = true;
|
||||
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.addBox(-4F, 0F, -2F, 8, 11, 4, delta);
|
||||
bipedBody.setRotationPoint(0F, 0F, 0F);
|
||||
@@ -97,6 +106,7 @@ public class ModelWizardArmour extends ModelArmourFixer {
|
||||
bipedHead.addChild(hatSegment4);
|
||||
bipedHead.addChild(hatSegment5);
|
||||
bipedHead.addChild(hatSegment6);
|
||||
bipedHead.addChild(hatBobble);
|
||||
}
|
||||
|
||||
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.rotateAngleY = this.bipedBody.rotateAngleY;
|
||||
this.robe.rotateAngleZ = (this.bipedLeftLeg.rotateAngleZ + this.bipedRightLeg.rotateAngleZ) / 2f;
|
||||
|
||||
this.hatBobble.showModel = Wizardry.tisTheSeason;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import electroblob.wizardry.item.ItemCrystal;
|
||||
import electroblob.wizardry.registry.WizardryBlocks;
|
||||
import electroblob.wizardry.registry.WizardryItems;
|
||||
import net.minecraft.client.renderer.block.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.block.model.ModelBakery;
|
||||
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
|
||||
import net.minecraft.client.renderer.block.statemap.StateMap;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
@@ -66,10 +67,10 @@ public final class WizardryModels {
|
||||
|
||||
registerMultiTexturedModel((ItemCrystal)WizardryItems.magic_crystal);
|
||||
|
||||
registerItemModel(WizardryItems.magic_wand);
|
||||
registerItemModel(WizardryItems.apprentice_wand);
|
||||
registerItemModel(WizardryItems.advanced_wand);
|
||||
registerItemModel(WizardryItems.master_wand);
|
||||
registerWandModel(WizardryItems.magic_wand);
|
||||
registerWandModel(WizardryItems.apprentice_wand);
|
||||
registerWandModel(WizardryItems.advanced_wand);
|
||||
registerWandModel(WizardryItems.master_wand);
|
||||
|
||||
registerItemModel(WizardryItems.spell_book);
|
||||
// Wildcard registered for wizard trades.
|
||||
@@ -77,37 +78,37 @@ public final class WizardryModels {
|
||||
registerItemModel(WizardryItems.arcane_tome);
|
||||
registerItemModel(WizardryItems.wizard_handbook);
|
||||
|
||||
registerItemModel(WizardryItems.novice_fire_wand);
|
||||
registerItemModel(WizardryItems.novice_ice_wand);
|
||||
registerItemModel(WizardryItems.novice_lightning_wand);
|
||||
registerItemModel(WizardryItems.novice_necromancy_wand);
|
||||
registerItemModel(WizardryItems.novice_earth_wand);
|
||||
registerItemModel(WizardryItems.novice_sorcery_wand);
|
||||
registerItemModel(WizardryItems.novice_healing_wand);
|
||||
registerWandModel(WizardryItems.novice_fire_wand);
|
||||
registerWandModel(WizardryItems.novice_ice_wand);
|
||||
registerWandModel(WizardryItems.novice_lightning_wand);
|
||||
registerWandModel(WizardryItems.novice_necromancy_wand);
|
||||
registerWandModel(WizardryItems.novice_earth_wand);
|
||||
registerWandModel(WizardryItems.novice_sorcery_wand);
|
||||
registerWandModel(WizardryItems.novice_healing_wand);
|
||||
|
||||
registerItemModel(WizardryItems.apprentice_fire_wand);
|
||||
registerItemModel(WizardryItems.apprentice_ice_wand);
|
||||
registerItemModel(WizardryItems.apprentice_lightning_wand);
|
||||
registerItemModel(WizardryItems.apprentice_necromancy_wand);
|
||||
registerItemModel(WizardryItems.apprentice_earth_wand);
|
||||
registerItemModel(WizardryItems.apprentice_sorcery_wand);
|
||||
registerItemModel(WizardryItems.apprentice_healing_wand);
|
||||
registerWandModel(WizardryItems.apprentice_fire_wand);
|
||||
registerWandModel(WizardryItems.apprentice_ice_wand);
|
||||
registerWandModel(WizardryItems.apprentice_lightning_wand);
|
||||
registerWandModel(WizardryItems.apprentice_necromancy_wand);
|
||||
registerWandModel(WizardryItems.apprentice_earth_wand);
|
||||
registerWandModel(WizardryItems.apprentice_sorcery_wand);
|
||||
registerWandModel(WizardryItems.apprentice_healing_wand);
|
||||
|
||||
registerItemModel(WizardryItems.advanced_fire_wand);
|
||||
registerItemModel(WizardryItems.advanced_ice_wand);
|
||||
registerItemModel(WizardryItems.advanced_lightning_wand);
|
||||
registerItemModel(WizardryItems.advanced_necromancy_wand);
|
||||
registerItemModel(WizardryItems.advanced_earth_wand);
|
||||
registerItemModel(WizardryItems.advanced_sorcery_wand);
|
||||
registerItemModel(WizardryItems.advanced_healing_wand);
|
||||
registerWandModel(WizardryItems.advanced_fire_wand);
|
||||
registerWandModel(WizardryItems.advanced_ice_wand);
|
||||
registerWandModel(WizardryItems.advanced_lightning_wand);
|
||||
registerWandModel(WizardryItems.advanced_necromancy_wand);
|
||||
registerWandModel(WizardryItems.advanced_earth_wand);
|
||||
registerWandModel(WizardryItems.advanced_sorcery_wand);
|
||||
registerWandModel(WizardryItems.advanced_healing_wand);
|
||||
|
||||
registerItemModel(WizardryItems.master_fire_wand);
|
||||
registerItemModel(WizardryItems.master_ice_wand);
|
||||
registerItemModel(WizardryItems.master_lightning_wand);
|
||||
registerItemModel(WizardryItems.master_necromancy_wand);
|
||||
registerItemModel(WizardryItems.master_earth_wand);
|
||||
registerItemModel(WizardryItems.master_sorcery_wand);
|
||||
registerItemModel(WizardryItems.master_healing_wand);
|
||||
registerWandModel(WizardryItems.master_fire_wand);
|
||||
registerWandModel(WizardryItems.master_ice_wand);
|
||||
registerWandModel(WizardryItems.master_lightning_wand);
|
||||
registerWandModel(WizardryItems.master_necromancy_wand);
|
||||
registerWandModel(WizardryItems.master_earth_wand);
|
||||
registerWandModel(WizardryItems.master_sorcery_wand);
|
||||
registerWandModel(WizardryItems.master_healing_wand);
|
||||
|
||||
registerItemModel(WizardryItems.spectral_sword);
|
||||
registerItemModel(WizardryItems.spectral_pickaxe);
|
||||
@@ -294,24 +295,30 @@ public final class WizardryModels {
|
||||
|
||||
/**
|
||||
* Registers an item model, using the item's registry name as the model name (this convention makes it easier to
|
||||
* keep track of everything). Variant defaults to "normal". Registers the model for metadata 0 automatically, plus
|
||||
* all the other metadata values that the item can take, as defined in
|
||||
* {@link Item#getSubItems(CreativeTabs, NonNullList)}. The creative tab supplied
|
||||
* to the aforementioned method will be whichever one the item is in.
|
||||
* keep track of everything). Variant defaults to "normal". Registers the model for all metadata values.
|
||||
*/
|
||||
private static void registerItemModel(Item item){
|
||||
|
||||
if(item.getHasSubtypes()){
|
||||
NonNullList<ItemStack> items = NonNullList.create();
|
||||
item.getSubItems(item.getCreativeTab(), items); // Client-only method, but we're client-side so this is OK.
|
||||
for(ItemStack stack : items){
|
||||
ModelLoader.setCustomModelResourceLocation(item, stack.getMetadata(),
|
||||
new ModelResourceLocation(item.getRegistryName(), "inventory"));
|
||||
}
|
||||
}
|
||||
// Changing the last parameter from null to "inventory" fixed the item/block model weirdness. No idea why!
|
||||
ModelLoader.setCustomModelResourceLocation(item, 0,
|
||||
new ModelResourceLocation(item.getRegistryName(), "inventory"));
|
||||
ModelBakery.registerItemVariants(item, new ModelResourceLocation(item.getRegistryName(), "inventory"));
|
||||
// Assigns the model for all metadata values
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -525,30 +525,42 @@ public abstract class ParticleWizardry extends Particle {
|
||||
|
||||
|
||||
// =============================================== 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,
|
||||
* 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];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/** 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
|
||||
* 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. */
|
||||
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];
|
||||
|
||||
for(int i=0; i<m; i++){
|
||||
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;
|
||||
// It's more logical to use the model's texture size, but some classes don't bother setting it properly
|
||||
// (e.g. ModelVillager), so to get the correct dimensions I'm getting them from the first box instead.
|
||||
if(model.boxList != null && model.boxList.get(0) != null){
|
||||
if(model.boxList != null && model.boxList.size() >= 1 && model.boxList.get(0) != null){
|
||||
scaleX = (double)model.boxList.get(0).textureWidth / 16d;
|
||||
scaleY = (double)model.boxList.get(0).textureHeight / 16d;
|
||||
}else{ // Fallback to model fields; should never be needed
|
||||
@@ -121,11 +121,26 @@ public class LayerFrost implements LayerRenderer<EntityLivingBase> {
|
||||
}
|
||||
GlStateManager.scale(scaleX, scaleY, 1);
|
||||
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
|
||||
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){
|
||||
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).bipedLeftArmwear.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.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
|
||||
GlStateManager.matrixMode(GL11.GL_TEXTURE);
|
||||
|
||||
@@ -42,6 +42,7 @@ public class RenderArcaneLock {
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.enableBlend();
|
||||
boolean lighting = GL11.glIsEnabled(GL11.GL_LIGHTING);
|
||||
GlStateManager.disableLighting();
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240, 240);
|
||||
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);
|
||||
|
||||
for(TileEntity tileentity : tileentities){
|
||||
|
||||
if(tileentity == null) continue; // What the heck VoxelMap
|
||||
|
||||
if(tileentity.getDistanceSq(origin.x, origin.y, origin.z) <= tileentity.getMaxRenderDistanceSquared()
|
||||
&& tileentity.getTileData().hasUniqueId(ArcaneLock.NBT_KEY)){
|
||||
@@ -82,7 +85,9 @@ public class RenderArcaneLock {
|
||||
|
||||
GlStateManager.disableBlend();
|
||||
GlStateManager.enableTexture2D();
|
||||
GlStateManager.enableLighting();
|
||||
if (lighting) {
|
||||
GlStateManager.enableLighting();
|
||||
}
|
||||
GlStateManager.disableRescaleNormal();
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
@@ -53,9 +53,8 @@ public class RenderBlackHole extends Render<EntityBlackHole> {
|
||||
(float)blackhole.ticksExisted / 10);
|
||||
}
|
||||
if(blackhole.ticksExisted > blackhole.lifetime - 10){
|
||||
GlStateManager.scale((float)(blackhole.lifetime - blackhole.ticksExisted) / 10,
|
||||
(float)(blackhole.lifetime - blackhole.ticksExisted) / 10,
|
||||
(float)(blackhole.lifetime - blackhole.ticksExisted) / 10);
|
||||
float scale = Math.max(0, (float)(blackhole.lifetime - blackhole.ticksExisted) / 10);
|
||||
GlStateManager.scale(scale, scale, scale);
|
||||
}
|
||||
|
||||
this.bindTexture(texture);
|
||||
|
||||
@@ -190,7 +190,8 @@ public class CommandCastSpell extends CommandBase {
|
||||
}
|
||||
|
||||
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)){
|
||||
|
||||
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(
|
||||
new TextComponentTranslation("commands." + Wizardry.MODID + ":discoverspell.clear", player.getName()));
|
||||
}else if(all){
|
||||
data.spellsDiscovered.addAll(Spell.getSpells(Spell.allSpells));
|
||||
data.spellsDiscovered.addAll(Spell.getAllSpells());
|
||||
if(server.sendCommandFeedback()) sender.sendMessage(
|
||||
new TextComponentTranslation("commands." + Wizardry.MODID + ":discoverspell.all", player.getName()));
|
||||
}else{
|
||||
|
||||
@@ -4,6 +4,7 @@ import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.data.SpellEmitterData;
|
||||
import electroblob.wizardry.event.SpellCastEvent;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import electroblob.wizardry.util.NBTExtras;
|
||||
import electroblob.wizardry.util.SpellModifiers;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
@@ -129,7 +130,7 @@ public class SpellEmitter implements ITickable {
|
||||
nbt.setDouble("z", z);
|
||||
nbt.setInteger("direction", direction.getIndex());
|
||||
nbt.setInteger("duration", duration);
|
||||
nbt.setTag("modifiers", modifiers.toNBT());
|
||||
NBTExtras.storeTagSafely(nbt, "modifiers", modifiers.toNBT());
|
||||
nbt.setInteger("castingTick", castingTick);
|
||||
|
||||
return nbt;
|
||||
|
||||
@@ -12,9 +12,9 @@ import java.util.Random;
|
||||
public enum Tier {
|
||||
|
||||
NOVICE(700, 3, 12, 0, new Style().setColor(TextFormatting.WHITE), "novice"),
|
||||
APPRENTICE(1000, 5, 5, 4000, new Style().setColor(TextFormatting.AQUA), "apprentice"),
|
||||
ADVANCED(1500, 7, 2, 6000, new Style().setColor(TextFormatting.DARK_BLUE), "advanced"),
|
||||
MASTER(2500, 9, 1, 10000, new Style().setColor(TextFormatting.DARK_PURPLE), "master");
|
||||
APPRENTICE(1000, 5, 5, 2000, new Style().setColor(TextFormatting.AQUA), "apprentice"),
|
||||
ADVANCED(1500, 7, 2, 3500, new Style().setColor(TextFormatting.DARK_BLUE), "advanced"),
|
||||
MASTER(2500, 9, 1, 6000, new Style().setColor(TextFormatting.DARK_PURPLE), "master");
|
||||
|
||||
/** Maximum mana a wand of this tier can store. */
|
||||
public final int maxCharge;
|
||||
|
||||
@@ -7,6 +7,7 @@ import electroblob.wizardry.packet.WizardryPacketHandler;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.spell.None;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import electroblob.wizardry.util.NBTExtras;
|
||||
import electroblob.wizardry.util.SpellModifiers;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
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("castingTick", castingTick);
|
||||
nbt.setTag("modifiers", modifiers.toNBT());
|
||||
NBTExtras.storeTagSafely(nbt, "modifiers", modifiers.toNBT());
|
||||
|
||||
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 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(DispenserCastingData.get((TileEntityDispenser)tileentity) != null){
|
||||
DispenserCastingData.get((TileEntityDispenser)tileentity).update();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package electroblob.wizardry.data;
|
||||
|
||||
import electroblob.wizardry.util.NBTExtras;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
@@ -89,7 +90,7 @@ public interface IStoredVariable<T> extends IVariable<T> {
|
||||
|
||||
@Override
|
||||
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
|
||||
|
||||
@@ -91,7 +91,7 @@ public class SpellEmitterData extends WorldSavedData {
|
||||
|
||||
@Override
|
||||
public NBTTagCompound writeToNBT(NBTTagCompound compound){
|
||||
compound.setTag("emitters", NBTExtras.listToNBT(emitters, SpellEmitter::toNBT));
|
||||
NBTExtras.storeTagSafely(compound, "emitters", NBTExtras.listToNBT(emitters, SpellEmitter::toNBT));
|
||||
return compound;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.packet.PacketGlyphData;
|
||||
import electroblob.wizardry.packet.WizardryPacketHandler;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import electroblob.wizardry.util.NBTExtras;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
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. */
|
||||
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));
|
||||
}
|
||||
|
||||
for(Spell spell : Spell.getSpells(Spell.allSpells)){
|
||||
for(Spell spell : Spell.getAllSpells()){
|
||||
if(!randomDescriptions.containsKey(spell))
|
||||
randomDescriptions.put(spell, generateRandomDescription(world.rand));
|
||||
}
|
||||
@@ -161,7 +162,7 @@ public class SpellGlyphData extends WorldSavedData {
|
||||
|
||||
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
|
||||
// The description is now also included; there's no point in making a second compound tag!
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
@@ -171,7 +172,7 @@ public class SpellGlyphData extends WorldSavedData {
|
||||
tagList.appendTag(tag);
|
||||
}
|
||||
|
||||
nbt.setTag("spellGlyphData", tagList);
|
||||
NBTExtras.storeTagSafely(nbt, "spellGlyphData", tagList);
|
||||
|
||||
return nbt;
|
||||
}
|
||||
|
||||
@@ -515,12 +515,12 @@ public class WizardData implements INBTSerializable<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));
|
||||
|
||||
// Mmmmmm Java 8....
|
||||
properties.setTag("allies", NBTExtras.listToNBT(this.allies, NBTUtil::createUUIDTag));
|
||||
properties.setTag("allyNames", NBTExtras.listToNBT(this.allyNames, NBTTagString::new));
|
||||
NBTExtras.storeTagSafely(properties, "allies", NBTExtras.listToNBT(this.allies, NBTUtil::createUUIDTag));
|
||||
NBTExtras.storeTagSafely(properties, "allyNames", NBTExtras.listToNBT(this.allyNames, NBTTagString::new));
|
||||
|
||||
// Might be worth converting this over to WizardryUtilities.listToNBT.
|
||||
int[] spells = new int[this.spellsDiscovered.size()];
|
||||
@@ -531,7 +531,7 @@ public class WizardData implements INBTSerializable<NBTTagCompound> {
|
||||
}
|
||||
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)));
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import electroblob.wizardry.util.AllyDesignationSystem;
|
||||
import electroblob.wizardry.util.MagicDamage;
|
||||
import electroblob.wizardry.util.NBTExtras;
|
||||
import electroblob.wizardry.util.WizardryUtilities;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import net.minecraft.block.Block;
|
||||
@@ -183,7 +184,7 @@ public class EntityLevitatingBlock extends EntityFallingBlock implements IEntity
|
||||
NBTBase nbtbase = this.tileEntityData.getTag(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(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){
|
||||
WizardryUtilities.getRider(this).attackEntityFrom(
|
||||
MagicDamage.causeIndirectMagicDamage(this, getCaster(), DamageType.MAGIC),
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package electroblob.wizardry.entity.construct;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import electroblob.wizardry.util.WizardryUtilities;
|
||||
|
||||
@@ -80,8 +80,8 @@ public class EntityHammer extends EntityMagicConstruct {
|
||||
|
||||
if(this.world.isRemote && this.ticksExisted % 3 == 0){
|
||||
ParticleBuilder.create(Type.SPARK)
|
||||
.pos(this.posX - 0.5d + rand.nextDouble(), this.posY + 2 * rand.nextDouble(), this.posZ - 0.5d + rand.nextDouble())
|
||||
.spawn(world);
|
||||
.pos(this.posX - 0.5d + rand.nextDouble(), this.posY + 2 * rand.nextDouble(), this.posZ - 0.5d + rand.nextDouble())
|
||||
.spawn(world);
|
||||
}
|
||||
|
||||
this.prevPosX = this.posX;
|
||||
@@ -103,39 +103,37 @@ public class EntityHammer extends EntityMagicConstruct {
|
||||
this.rotationPitch = 0;
|
||||
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,
|
||||
this.posY + 1, this.posZ, world);
|
||||
int maxTargets = Spells.lightning_hammer.getProperty(LightningHammer.SECONDARY_MAX_TARGETS).intValue();
|
||||
while(targets.size() > maxTargets) targets.remove(targets.size() - 1);
|
||||
|
||||
int maxTargets = Spells.lightning_hammer.getProperty(LightningHammer.SECONDARY_MAX_TARGETS).intValue();
|
||||
while(targets.size() > maxTargets) targets.remove(targets.size() - 1);
|
||||
for(EntityLivingBase target : targets){
|
||||
|
||||
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.getEntityBoundingBox().minY + target.height, target.posZ);
|
||||
}
|
||||
target.playSound(WizardrySounds.ENTITY_HAMMER_ATTACK, 1.0F, rand.nextFloat() * 0.4F + 1.5F);
|
||||
|
||||
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(
|
||||
this, getCaster(), DamageType.SHOCK), damage);
|
||||
WizardryUtilities.applyStandardKnockback(this, target);
|
||||
}else{
|
||||
target.attackEntityFrom(DamageSource.MAGIC, damage);
|
||||
}
|
||||
if(this.getCaster() != null){
|
||||
WizardryUtilities.attackEntityWithoutKnockback(target, MagicDamage.causeIndirectMagicDamage(
|
||||
this, getCaster(), DamageType.SHOCK), damage);
|
||||
WizardryUtilities.applyStandardKnockback(this, target);
|
||||
}else{
|
||||
target.attackEntityFrom(DamageSource.MAGIC, damage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ public class EntityHealAura extends EntityMagicConstruct {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,9 +29,9 @@ public class EntityIceSpike extends EntityMagicConstruct {
|
||||
this.setRotation(-facing.getHorizontalAngle(), WizardryUtilities.getPitch(facing));
|
||||
float yaw = (-facing.getHorizontalAngle()) * (float)Math.PI/180;
|
||||
float pitch = (WizardryUtilities.getPitch(facing) - 90) * (float)Math.PI/180;
|
||||
Vec3d min = new Vec3d(-width/2, 0, -width/2).rotatePitch(pitch).rotateYaw(yaw);
|
||||
Vec3d max = new Vec3d(width/2, height, width/2).rotatePitch(pitch).rotateYaw(yaw);
|
||||
this.setEntityBoundingBox(new AxisAlignedBB(this.getPositionVector().add(min), this.getPositionVector().add(max)));
|
||||
Vec3d min = this.getPositionVector().add(new Vec3d(-width/2, 0, -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(min.x, min.y, min.z, max.x, max.y, max.z));
|
||||
}
|
||||
|
||||
public EnumFacing getFacing(){
|
||||
|
||||
@@ -213,6 +213,7 @@ public class EntityAIAttackSpell<T extends EntityLiving & ISpellCaster> extends
|
||||
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.isContinuous){
|
||||
|
||||
@@ -35,11 +35,17 @@ import net.minecraft.world.DifficultyInstance;
|
||||
import net.minecraft.world.EnumDifficulty;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.util.Constants.NBT;
|
||||
import net.minecraftforge.event.entity.living.LivingSpawnEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.eventhandler.Event;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
|
||||
@Mod.EventBusSubscriber
|
||||
public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntityAdditionalSpawnData {
|
||||
|
||||
private EntityAIAttackSpell<EntityEvilWizard> spellCastingAI = new EntityAIAttackSpell<>(this, 0.5D, 14.0F, 30, 50);
|
||||
@@ -68,6 +74,7 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity
|
||||
// Field implementations
|
||||
private List<Spell> spells = new ArrayList<Spell>(4);
|
||||
private Spell continuousSpell;
|
||||
private int spellCounter;
|
||||
|
||||
public EntityEvilWizard(World world){
|
||||
|
||||
@@ -169,6 +176,16 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity
|
||||
public Spell getContinuousSpell(){
|
||||
return this.continuousSpell;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpellCounter(int count){
|
||||
spellCounter = count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSpellCounter(){
|
||||
return spellCounter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAimingError(EnumDifficulty difficulty){
|
||||
@@ -246,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
|
||||
if(player.isCreative() && stack.getItem() instanceof ItemSpellBook){
|
||||
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!
|
||||
player.sendMessage(new TextComponentTranslation("item." + Wizardry.MODID + ":spell_book.apply_to_wizard",
|
||||
this.getDisplayName(), this.spells.set(rand.nextInt(3) + 1, spell).getNameForTranslationFormatted(),
|
||||
@@ -263,9 +280,9 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity
|
||||
super.writeEntityToNBT(nbt);
|
||||
nbt.setInteger("element", this.getElement().ordinal());
|
||||
nbt.setInteger("skin", this.textureIndex);
|
||||
nbt.setTag("spells", 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.setTag("groupUUIDs", NBTExtras.listToNBT(groupUUIDs, NBTUtil::createUUIDTag));
|
||||
NBTExtras.storeTagSafely(nbt, "groupUUIDs", NBTExtras.listToNBT(groupUUIDs, NBTUtil::createUUIDTag));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -283,16 +300,6 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity
|
||||
public int getMaxSpawnedInChunk(){
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getCanSpawnHere(){
|
||||
// Evil wizards can only spawn in the specified dimensions
|
||||
for(int id : Wizardry.settings.mobSpawnDimensions){
|
||||
if(this.dimension == id) return super.getCanSpawnHere();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canDespawn(){
|
||||
@@ -373,7 +380,7 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity
|
||||
// All wizards know magic missile, even if it is disabled.
|
||||
spells.add(Spells.magic_missile);
|
||||
|
||||
Tier maxTier = EntityWizard.populateSpells(spells, element, 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;
|
||||
// it picks a random wand which is at least a high enough tier for the spells the wizard has.
|
||||
@@ -393,4 +400,13 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity
|
||||
textureIndex = data.readInt();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onCheckSpawnEvent(LivingSpawnEvent.CheckSpawn event){
|
||||
// We have no way of checking if it's a spawner in getCanSpawnHere() so this has to be done here instead
|
||||
if(event.getEntityLiving() instanceof EntityEvilWizard && !event.isSpawner()){
|
||||
if(!ArrayUtils.contains(Wizardry.settings.mobSpawnDimensions, event.getWorld().provider.getDimension()))
|
||||
event.setResult(Event.Result.DENY);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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(7, new EntityAILookIdle(this));
|
||||
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()));
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,13 @@ import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.EnumParticleTypes;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.event.entity.living.LivingSpawnEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.eventhandler.Event;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
@Mod.EventBusSubscriber
|
||||
public class EntityIceWraith extends EntityBlazeMinion {
|
||||
|
||||
/** The version from EntityLivingBase is only used in onLivingUpdate, so it can safely be copied. */
|
||||
@@ -185,12 +191,16 @@ public class EntityIceWraith extends EntityBlazeMinion {
|
||||
|
||||
@Override
|
||||
public boolean getCanSpawnHere(){
|
||||
// Only spawns in the specified dimensions
|
||||
for(int id : Wizardry.settings.mobSpawnDimensions){
|
||||
if(this.dimension == id) return super.getCanSpawnHere() && this.isValidLightLevel();
|
||||
}
|
||||
return super.getCanSpawnHere() && this.isValidLightLevel();
|
||||
}
|
||||
|
||||
return false;
|
||||
@SubscribeEvent
|
||||
public static void onCheckSpawnEvent(LivingSpawnEvent.CheckSpawn event){
|
||||
// We have no way of checking if it's a spawner in getCanSpawnHere() so this has to be done here instead
|
||||
if(event.getEntityLiving() instanceof EntityLightningWraith && !event.isSpawner()){
|
||||
if(!ArrayUtils.contains(Wizardry.settings.mobSpawnDimensions, event.getWorld().provider.getDimension()))
|
||||
event.setResult(Event.Result.DENY);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,7 +13,13 @@ import net.minecraft.init.MobEffects;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.event.entity.living.LivingSpawnEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.eventhandler.Event;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
@Mod.EventBusSubscriber
|
||||
public class EntityLightningWraith extends EntityBlazeMinion {
|
||||
|
||||
public EntityLightningWraith(World world){
|
||||
@@ -74,14 +80,17 @@ public class EntityLightningWraith extends EntityBlazeMinion {
|
||||
|
||||
@Override
|
||||
public boolean getCanSpawnHere(){
|
||||
// Only spawns in the specified dimensions, during thunderstorms
|
||||
if(!world.isThundering()) return false;
|
||||
return super.getCanSpawnHere() && this.isValidLightLevel();
|
||||
}
|
||||
|
||||
for(int id : Wizardry.settings.mobSpawnDimensions){
|
||||
if(this.dimension == id) return super.getCanSpawnHere() && this.isValidLightLevel();
|
||||
@SubscribeEvent
|
||||
public static void onCheckSpawnEvent(LivingSpawnEvent.CheckSpawn event){
|
||||
// We have no way of checking if it's a spawner in getCanSpawnHere() so this has to be done here instead
|
||||
if(event.getEntityLiving() instanceof EntityLightningWraith && !event.isSpawner()){
|
||||
if(!event.getWorld().isThundering()) event.setResult(Event.Result.DENY);
|
||||
if(!ArrayUtils.contains(Wizardry.settings.mobSpawnDimensions, event.getWorld().provider.getDimension()))
|
||||
event.setResult(Event.Result.DENY);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -30,6 +30,7 @@ public class EntityPhoenix extends EntitySummonedCreature implements ISpellCaste
|
||||
private EntityAIAttackSpell<EntityPhoenix> spellAttackAI = new EntityAIAttackSpell<>(this, AISpeed, 15f, 60, 140);
|
||||
|
||||
private Spell continuousSpell;
|
||||
private int spellCounter;
|
||||
|
||||
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.targetTasks.addTask(0, new EntityAIMoveTowardsTarget(this, 1, 10));
|
||||
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()));
|
||||
|
||||
this.setAIMoveSpeed((float)AISpeed);
|
||||
@@ -76,6 +77,16 @@ public class EntityPhoenix extends EntitySummonedCreature implements ISpellCaste
|
||||
continuousSpell = spell;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpellCounter(int count){
|
||||
spellCounter = count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSpellCounter(){
|
||||
return spellCounter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasRangedAttack(){
|
||||
return true;
|
||||
|
||||
@@ -45,7 +45,7 @@ public class EntityShadowWraith extends EntitySummonedCreature implements ISpell
|
||||
this.tasks.addTask(2, new EntityAIWander(this, AISpeed));
|
||||
this.tasks.addTask(3, new EntityAILookIdle(this));
|
||||
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()));
|
||||
|
||||
this.setAIMoveSpeed((float)AISpeed);
|
||||
@@ -61,21 +61,6 @@ public class EntityShadowWraith extends EntitySummonedCreature implements ISpell
|
||||
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
|
||||
protected void applyEntityAttributes(){
|
||||
super.applyEntityAttributes();
|
||||
|
||||
@@ -59,21 +59,6 @@ public class EntityStormElemental extends EntitySummonedCreature implements ISpe
|
||||
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
|
||||
protected void applyEntityAttributes(){
|
||||
super.applyEntityAttributes();
|
||||
|
||||
@@ -83,6 +83,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
|
||||
// Field implementations
|
||||
private List<Spell> spells = new ArrayList<Spell>(4);
|
||||
private Spell continuousSpell;
|
||||
private int spellCounter;
|
||||
|
||||
/** A set of the positions of the blocks that are part of this wizard's tower. */
|
||||
private Set<BlockPos> towerBlocks;
|
||||
@@ -187,7 +188,17 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
|
||||
public Spell getContinuousSpell(){
|
||||
return this.continuousSpell;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setSpellCounter(int count){
|
||||
spellCounter = count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSpellCounter(){
|
||||
return spellCounter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAimingError(EnumDifficulty difficulty){
|
||||
// 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
|
||||
if(!this.world.isRemote && this.livingSoundTime > -this.getTalkInterval() + 20){
|
||||
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
|
||||
protected SoundEvent getAmbientSound(){
|
||||
if(Wizardry.tisTheSeason) return WizardrySounds.ENTITY_WIZARD_HOHOHO;
|
||||
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
|
||||
if(player.isCreative() && stack.getItem() instanceof ItemSpellBook){
|
||||
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!
|
||||
player.sendMessage(new TextComponentTranslation("item." + Wizardry.MODID + ":spell_book.apply_to_wizard",
|
||||
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);
|
||||
|
||||
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("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){
|
||||
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),
|
||||
(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()){
|
||||
this.towerBlocks = new HashSet<>(NBTExtras.NBTToList(tagList, NBTUtil::getPosFromTag));
|
||||
}else{
|
||||
@@ -750,7 +763,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
|
||||
// All wizards know magic missile, even if it is disabled.
|
||||
spells.add(Spells.magic_missile);
|
||||
|
||||
Tier maxTier = populateSpells(spells, element, 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.
|
||||
ItemStack wand = new ItemStack(WizardryItems.getWand(maxTier, element));
|
||||
@@ -767,19 +780,22 @@ 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
|
||||
* 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 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 random A random number generator to use.
|
||||
* @return The tier of the highest-tier spell that was added to the list.
|
||||
*/
|
||||
static Tier populateSpells(List<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.
|
||||
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));
|
||||
|
||||
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.
|
||||
* <p></p>
|
||||
* 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
|
||||
* 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.
|
||||
* 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
|
||||
public List<Spell> getSpells();
|
||||
List<Spell> getSpells();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@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
|
||||
* 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
|
||||
* {@link Spells#none}. If the implementing class only ever uses one continuous spell, do <b>not</b> just return
|
||||
* that spell; the field must still be stored.
|
||||
* saved to NBT is up to you. If the implementing class only ever uses one continuous spell, do <b>not</b> just
|
||||
* return that spell; the field must still be stored.
|
||||
*/
|
||||
@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
|
||||
* 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.
|
||||
*/
|
||||
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).
|
||||
*/
|
||||
// This is what default methods are actually intended for!
|
||||
public default int getAimingError(EnumDifficulty difficulty) {
|
||||
default int getAimingError(EnumDifficulty 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.
|
||||
*/
|
||||
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 net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.projectile.EntitySmallFireball;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
|
||||
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){
|
||||
this.lifetime = lifetime;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package electroblob.wizardry.entity.projectile;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
@@ -44,15 +45,34 @@ public class EntityMagicMissile extends EntityMagicArrow {
|
||||
public void tickInAir(){
|
||||
|
||||
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(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);
|
||||
|
||||
if(Wizardry.tisTheSeason){
|
||||
|
||||
ParticleBuilder.create(Type.SPARKLE, rand, posX, posY, posZ, 0.03, true).clr(0.8f, 0.15f, 0.15f)
|
||||
.time(20 + rand.nextInt(10)).spawn(world);
|
||||
|
||||
ParticleBuilder.create(Type.SNOW).pos(posX, posY, posZ).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
|
||||
: target.getEntityBoundingBox().minY + (double)(target.height / 2.0f) - this.posY;
|
||||
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){
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ import electroblob.wizardry.util.ParticleBuilder.Type;
|
||||
import electroblob.wizardry.util.WizardryUtilities;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.MobEffects;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.util.EnumParticleTypes;
|
||||
@@ -66,12 +65,11 @@ public class EntitySmokeBomb extends EntityBomb {
|
||||
|
||||
for(EntityLivingBase target : targets){
|
||||
if(target != this.getThrower()){
|
||||
// Gives the target blindness if it is a player, mind trick otherwise (since this has the desired
|
||||
// Gives the target blindness, and mind trick if it's not a player (since this has the desired
|
||||
// effect of preventing targeting)
|
||||
if(target instanceof EntityPlayer){
|
||||
target.addPotionEffect(new PotionEffect(MobEffects.BLINDNESS, duration, 0));
|
||||
}else if(target instanceof EntityLiving){
|
||||
// New AI
|
||||
target.addPotionEffect(new PotionEffect(MobEffects.BLINDNESS, duration, 0));
|
||||
|
||||
if(target instanceof EntityLiving){
|
||||
((EntityLiving)target).setAttackTarget(null);
|
||||
target.addPotionEffect(new PotionEffect(WizardryPotions.mind_trick, duration, 0));
|
||||
}
|
||||
|
||||
@@ -58,6 +58,8 @@ public interface IConjuredItem {
|
||||
*/
|
||||
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();
|
||||
|
||||
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 tier2 = Tier.values()[stack.getItemDamage() - 1];
|
||||
|
||||
tooltip.add(tier.getDisplayNameWithFormatting());
|
||||
tooltip.add("\u00A77" + net.minecraft.client.resources.I18n.format("item." + Wizardry.MODID + ":arcane_tome.desc1",
|
||||
tier2.getDisplayNameWithFormatting()));
|
||||
tooltip.add("\u00A77" + net.minecraft.client.resources.I18n.format("item." + Wizardry.MODID + ":arcane_tome.desc2",
|
||||
tier.getDisplayNameWithFormatting() + "\u00A77"));
|
||||
Wizardry.proxy.addMultiLineDescription(tooltip, "item." + this.getRegistryName() + ".desc",
|
||||
tier2.getDisplayNameWithFormatting() + "\u00A77", tier.getDisplayNameWithFormatting() + "\u00A77");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -265,7 +265,7 @@ public class ItemArtefact extends Item {
|
||||
|
||||
if(artefact == WizardryItems.ring_condensing){
|
||||
|
||||
if(world.isRemote && player.ticksExisted % 150 == 0){
|
||||
if(player.ticksExisted % 150 == 0){
|
||||
for(ItemStack stack : WizardryUtilities.getHotbar(player)){
|
||||
// Needs to be both of these interfaces because this ring only recharges wands
|
||||
// (or more accurately, chargeable spellcasting items)
|
||||
@@ -276,7 +276,7 @@ public class ItemArtefact extends Item {
|
||||
|
||||
}else if(artefact == WizardryItems.amulet_arcane_defence){
|
||||
|
||||
if(world.isRemote && player.ticksExisted % 300 == 0){
|
||||
if(player.ticksExisted % 300 == 0){
|
||||
for(ItemStack stack : player.getArmorInventoryList()){
|
||||
// IManaStoringItem is sufficient, since anything in the armour slots is probably armour
|
||||
if(stack.getItem() instanceof IManaStoringItem)
|
||||
@@ -601,7 +601,7 @@ public class ItemArtefact extends Item {
|
||||
|
||||
}else if(artefact == WizardryItems.amulet_transience){
|
||||
|
||||
if(player.getHealth() <= 2 && player.world.rand.nextFloat() < 0.25f){
|
||||
if(player.getHealth() <= 6 && player.world.rand.nextFloat() < 0.25f){
|
||||
player.addPotionEffect(new PotionEffect(WizardryPotions.transience, 300));
|
||||
player.addPotionEffect(new PotionEffect(MobEffects.INVISIBILITY, 300, 0, false, false));
|
||||
}
|
||||
@@ -639,6 +639,7 @@ public class ItemArtefact extends Item {
|
||||
|
||||
WizardryUtilities.getEntitiesWithinRadius(3, player.posX, player.posY, player.posZ, world).stream()
|
||||
.filter(WizardryUtilities::isLiving)
|
||||
.filter(e -> e != player)
|
||||
.min(Comparator.comparingDouble(player::getDistanceSq))
|
||||
.ifPresent(target -> {
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package electroblob.wizardry.item;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.constants.Constants;
|
||||
import electroblob.wizardry.data.WizardData;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
@@ -11,11 +12,13 @@ import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
public class ItemBlankScroll extends Item implements IWorkbenchItem {
|
||||
|
||||
public ItemBlankScroll(){
|
||||
this.setCreativeTab(WizardryTabs.WIZARDRY);
|
||||
this.addPropertyOverride(new ResourceLocation("festive"), (s, w, e) -> Wizardry.tisTheSeason ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -45,10 +48,14 @@ public class ItemBlankScroll extends Item implements IWorkbenchItem {
|
||||
int cost = spell.getCost() * centre.getStack().getCount();
|
||||
// Continuous spell scrolls require enough mana to cast them for the duration defined in ItemScroll.
|
||||
if(spell.isContinuous) cost *= ItemScroll.CASTING_TIME / 20;
|
||||
|
||||
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
|
||||
crystals.decrStackSize(cost / Constants.MANA_PER_CRYSTAL + 1);
|
||||
crystals.decrStackSize(cost / manaPerItem + 1);
|
||||
centre.putStack(new ItemStack(WizardryItems.scroll, centre.getStack().getCount(), spell.metadata()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package electroblob.wizardry.item;
|
||||
import com.google.common.collect.Multimap;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardryPotions;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import electroblob.wizardry.util.MagicDamage;
|
||||
import electroblob.wizardry.util.MagicDamage.DamageType;
|
||||
import electroblob.wizardry.util.WizardryUtilities;
|
||||
@@ -81,6 +82,12 @@ public class ItemFrostAxe extends ItemAxe implements IConjuredItem {
|
||||
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
|
||||
public boolean hitEntity(ItemStack stack, EntityLivingBase target, EntityLivingBase wielder){
|
||||
if(!MagicDamage.isEntityImmune(DamageType.FROST, target))
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package electroblob.wizardry.item;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.data.SpellGlyphData;
|
||||
import electroblob.wizardry.event.SpellCastEvent;
|
||||
import electroblob.wizardry.event.SpellCastEvent.Source;
|
||||
import electroblob.wizardry.packet.PacketCastSpell;
|
||||
@@ -14,16 +13,12 @@ import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.EnumActionResult;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraft.util.*;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
import net.minecraftforge.oredict.OreDictionary;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -37,6 +32,7 @@ public class ItemScroll extends Item implements ISpellCastingItem {
|
||||
setHasSubtypes(true);
|
||||
setMaxStackSize(16);
|
||||
setCreativeTab(WizardryTabs.SPELLS);
|
||||
this.addPropertyOverride(new ResourceLocation("festive"), (s, w, e) -> Wizardry.tisTheSeason ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -51,13 +47,14 @@ public class ItemScroll extends Item implements ISpellCastingItem {
|
||||
|
||||
@Override
|
||||
public void getSubItems(CreativeTabs tab, NonNullList<ItemStack> list){
|
||||
|
||||
if(tab == WizardryTabs.SPELLS){
|
||||
// In this particular case, getTotalSpellCount() is a more efficient way of doing this since the spell instance
|
||||
// is not required, only the metadata.
|
||||
for(int i = 0; i < Spell.getTotalSpellCount(); i++){
|
||||
// i+1 is used so that the metadata ties up with the metadata() method. In other words, the none spell has metadata
|
||||
// 0 and since this is not used as a spell book the metadata starts at 1.
|
||||
list.add(new ItemStack(this, 1, i + 1));
|
||||
|
||||
List<Spell> spells = Spell.getAllSpells();
|
||||
spells.removeIf(s -> !s.applicableForItem(this));
|
||||
|
||||
for(Spell spell : spells){
|
||||
list.add(new ItemStack(this, 1, spell.metadata()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package electroblob.wizardry.item;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.WizardryGuiHandler;
|
||||
import electroblob.wizardry.constants.Tier;
|
||||
import electroblob.wizardry.data.SpellGlyphData;
|
||||
import electroblob.wizardry.registry.WizardryTabs;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
@@ -9,35 +11,41 @@ import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.EnumActionResult;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraft.util.*;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.relauncher.Side;
|
||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||
import net.minecraftforge.oredict.OreDictionary;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ItemSpellBook extends Item {
|
||||
|
||||
private static final Map<Tier, ResourceLocation> guiTextures = ImmutableMap.of(
|
||||
Tier.NOVICE, new ResourceLocation(Wizardry.MODID, "textures/gui/spell_book_novice.png"),
|
||||
Tier.APPRENTICE, new ResourceLocation(Wizardry.MODID, "textures/gui/spell_book_apprentice.png"),
|
||||
Tier.ADVANCED, new ResourceLocation(Wizardry.MODID, "textures/gui/spell_book_advanced.png"),
|
||||
Tier.MASTER, new ResourceLocation(Wizardry.MODID, "textures/gui/spell_book_master.png"));
|
||||
|
||||
public ItemSpellBook(){
|
||||
super();
|
||||
setHasSubtypes(true);
|
||||
setMaxStackSize(16);
|
||||
setCreativeTab(WizardryTabs.SPELLS);
|
||||
this.addPropertyOverride(new ResourceLocation("festive"), (s, w, e) -> Wizardry.tisTheSeason ? 1 : 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getSubItems(CreativeTabs tab, NonNullList<ItemStack> list){
|
||||
|
||||
if(tab == WizardryTabs.SPELLS){
|
||||
// In this particular case, getTotalSpellCount() is a more efficient way of doing this since the spell instance
|
||||
// is not required, only the metadata.
|
||||
for(int i = 0; i < Spell.getTotalSpellCount(); i++){
|
||||
// i+1 is used so that the metadata ties up with the metadata() method. In other words, the none spell has metadata
|
||||
// 0 and since this is not used as a spell book the metadata starts at 1.
|
||||
list.add(new ItemStack(this, 1, i + 1));
|
||||
|
||||
List<Spell> spells = Spell.getAllSpells();
|
||||
spells.removeIf(s -> !s.applicableForItem(this));
|
||||
|
||||
for(Spell spell : spells){
|
||||
list.add(new ItemStack(this, 1, spell.metadata()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -79,4 +87,12 @@ public class ItemSpellBook extends Item {
|
||||
return Wizardry.proxy.getFontRenderer(stack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the GUI texture to be used when this spell book is opened.
|
||||
* @param spell The spell for the book being opened.
|
||||
*/
|
||||
public ResourceLocation getGuiTexture(Spell spell){
|
||||
return guiTextures.get(spell.getTier());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
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
|
||||
if(spell.isContinuous) cost = getDistributedCost(cost, castingTick);
|
||||
@@ -436,7 +436,7 @@ public class ItemWand extends Item implements IWorkbenchItem, ISpellCastingItem,
|
||||
caster.setActiveHand(hand);
|
||||
|
||||
// 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
|
||||
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 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
|
||||
// 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)}
|
||||
* to modify wand mana from elsewhere. */
|
||||
* to modify armour mana from elsewhere. */
|
||||
@Override
|
||||
public void setDamage(ItemStack stack, int damage){
|
||||
// Overridden to stop repair things from 'repairing' the mana in wizard armour
|
||||
// This being armour, it's much easier to let its damage increase normally, but block it from being decreased
|
||||
if(stack.getItemDamage() < damage) super.setDamage(stack, damage);
|
||||
if(stack.getItemDamage() < damage) super.setDamage(stack, Math.min(damage, stack.getMaxDamage()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -178,9 +178,14 @@ public class ItemWizardArmour extends ItemArmor implements IWorkbenchItem, IMana
|
||||
|
||||
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(stack.hasTagCompound() && stack.getTagCompound().getBoolean("legendary")) s = "legendary_" + s;
|
||||
|
||||
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);
|
||||
double followRange = attribute == null ? 16 : attribute.getAttributeValue();
|
||||
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;
|
||||
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
|
||||
|
||||
@@ -108,10 +108,14 @@ public class RandomSpell extends LootFunction {
|
||||
// element = null;
|
||||
}
|
||||
|
||||
SpellProperties.Context spellContext = context.getLootedEntity() == null ? SpellProperties.Context.TREASURE
|
||||
: SpellProperties.Context.LOOTING;
|
||||
|
||||
// Here's a thought: does randomly selecting the element beforehand (as opposed to leaving it null and letting
|
||||
// the spell randomiser use any element) change the overall outcome at all?
|
||||
List<Spell> spellsList = Spell.getSpells(new Spell.TierElementFilter(tier, element, SpellProperties.Context.TREASURE));
|
||||
List<Spell> spellsList = Spell.getSpells(new Spell.TierElementFilter(tier, element, spellContext));
|
||||
|
||||
spellsList.removeIf(s -> !s.applicableForItem(stack.getItem()));
|
||||
if(stack.getItem() instanceof ItemScroll) spellsList.removeIf(s -> !s.isEnabled(SpellProperties.Context.SCROLL));
|
||||
if(stack.getItem() instanceof ItemSpellBook) spellsList.removeIf(s -> !s.isEnabled(SpellProperties.Context.BOOK));
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.entity.living.ISpellCaster;
|
||||
import electroblob.wizardry.item.ItemScroll;
|
||||
import electroblob.wizardry.item.ItemSpellBook;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
@@ -33,13 +34,18 @@ public class WizardSpell extends LootFunction {
|
||||
@Override
|
||||
public ItemStack apply(ItemStack stack, Random random, LootContext context){
|
||||
|
||||
if(!(stack.getItem() instanceof ItemSpellBook)) Wizardry.logger
|
||||
if(!(stack.getItem() instanceof ItemSpellBook) && !(stack.getItem() instanceof ItemScroll)) Wizardry.logger
|
||||
.warn("Applying the wizard_spell loot function to an item that isn't a spell book or scroll.");
|
||||
|
||||
if(context.getLootedEntity() instanceof ISpellCaster){
|
||||
List<Spell> spells = ((ISpellCaster)context.getLootedEntity()).getSpells();
|
||||
spells.remove(Spells.magic_missile); // Can't drop magic missile
|
||||
stack.setItemDamage(spells.get(random.nextInt(spells.size())).metadata());
|
||||
spells.removeIf(s -> !s.applicableForItem(stack.getItem()));
|
||||
if(spells.isEmpty()){
|
||||
Wizardry.logger.warn("Tried to apply the wizard_spell loot function to an item, but none of the looted entity's spells were applicable for that item. This is probably a bug!");
|
||||
}else{
|
||||
stack.setItemDamage(spells.get(random.nextInt(spells.size())).metadata());
|
||||
}
|
||||
}else{
|
||||
Wizardry.logger.warn("Applying the wizard_spell loot function to an entity that isn't a spell caster.");
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ public class BehaviourSpellDispense extends BehaviorDispenseOptional {
|
||||
if(world.isSideSolid(source.getBlockPos().offset(direction), direction.getOpposite())) return stack;
|
||||
|
||||
// If the scroll can never be cast by a dispenser, it should be dispensed as an item.
|
||||
if(!spell.canBeCastByDispensers()) return super.dispenseStack(source, stack);
|
||||
if(!spell.canBeCastBy(source.getBlockTileEntity())) return super.dispenseStack(source, stack);
|
||||
|
||||
SpellModifiers modifiers = new SpellModifiers();
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ public abstract class Forfeit {
|
||||
|
||||
event.setCanceled(true);
|
||||
|
||||
Forfeit forfeit = getRandomForfeit(event.getWorld().rand, event.getSpell().getTier(), event.getSpell().getElement());
|
||||
Forfeit forfeit = getRandomForfeit(data.synchronisedRandom, event.getSpell().getTier(), event.getSpell().getElement());
|
||||
|
||||
if(forfeit == null){ // Should never happen, but just in case...
|
||||
if(!event.getWorld().isRemote) player.sendMessage(new TextComponentTranslation("forfeit.ebwizardry:do_nothing"));
|
||||
|
||||
@@ -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(PacketSyncAdvancements.class, PacketSyncAdvancements.Message.class);
|
||||
registerMessage(PacketRequestAdvancementSync.class, PacketRequestAdvancementSync.Message.class);
|
||||
registerMessage(PacketEndSlowTime.class, PacketEndSlowTime.Message.class);
|
||||
registerMessage(PacketResurrection.class, PacketResurrection.Message.class);
|
||||
registerMessage(PacketCastSpellAtPos.class, PacketCastSpellAtPos.Message.class);
|
||||
registerMessage(PacketEmitterData.class, PacketEmitterData.Message.class);
|
||||
|
||||
@@ -2,6 +2,7 @@ package electroblob.wizardry.potion;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.registry.WizardryPotions;
|
||||
import electroblob.wizardry.util.NBTExtras;
|
||||
import electroblob.wizardry.util.WizardryUtilities;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
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
|
||||
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)));
|
||||
|
||||
@@ -2,8 +2,6 @@ package electroblob.wizardry.potion;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.item.ItemArtefact;
|
||||
import electroblob.wizardry.packet.PacketEndSlowTime;
|
||||
import electroblob.wizardry.packet.WizardryPacketHandler;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardryItems;
|
||||
import electroblob.wizardry.registry.WizardryPotions;
|
||||
@@ -17,11 +15,15 @@ import net.minecraft.entity.IProjectile;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.projectile.EntityArrow;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent;
|
||||
import net.minecraftforge.event.entity.living.PotionEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.PlayerEvent;
|
||||
import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@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
|
||||
|
||||
public static final String NBT_KEY = "time_slowed";
|
||||
|
||||
public PotionSlowTime(boolean isBadEffect, int liquidColour){
|
||||
super(isBadEffect, liquidColour, new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icon_slow_time.png"));
|
||||
this.setPotionName("potion." + Wizardry.MODID + ":slow_time");
|
||||
@@ -61,6 +65,8 @@ public class PotionSlowTime extends PotionMagicEffect implements ISyncedPotion {
|
||||
|
||||
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
|
||||
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
|
||||
public static void onLivingUpdateEvent(LivingUpdateEvent event){
|
||||
|
||||
@@ -150,23 +179,16 @@ public class PotionSlowTime extends PotionMagicEffect implements ISyncedPotion {
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onPotionExpiryEvent(PotionEvent.PotionExpiryEvent event){
|
||||
if(event.getPotionEffect() != null && event.getPotionEffect().getPotion() == WizardryPotions.slow_time){
|
||||
unblockNearbyEntities(event.getEntityLiving());
|
||||
if(!event.getEntity().world.isRemote){
|
||||
WizardryPacketHandler.net.sendToDimension(new PacketEndSlowTime.Message(event.getEntityLiving()), event.getEntity().dimension);
|
||||
}
|
||||
}
|
||||
public static void tick(TickEvent.WorldTickEvent event){
|
||||
if(!event.world.isRemote && event.phase == TickEvent.Phase.END) cleanUpEntities(event.world);
|
||||
}
|
||||
|
||||
// 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
|
||||
public static void onPotionRemoveEvent(PotionEvent.PotionRemoveEvent event){
|
||||
if(event.getPotionEffect() != null && event.getPotionEffect().getPotion() == WizardryPotions.slow_time){
|
||||
unblockNearbyEntities(event.getEntityLiving());
|
||||
if(!event.getEntity().world.isRemote){
|
||||
WizardryPacketHandler.net.sendToDimension(new PacketEndSlowTime.Message(event.getEntityLiving()), event.getEntity().dimension);
|
||||
}
|
||||
}
|
||||
public static void onPlayerLoggedOutEvent(PlayerEvent.PlayerLoggedOutEvent event){
|
||||
if(event.player.updateBlocked) event.player.updateBlocked = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import electroblob.wizardry.entity.construct.*;
|
||||
import electroblob.wizardry.entity.living.*;
|
||||
import electroblob.wizardry.entity.projectile.*;
|
||||
import electroblob.wizardry.spell.*;
|
||||
import net.minecraft.entity.projectile.EntitySnowball;
|
||||
import net.minecraft.init.MobEffects;
|
||||
import net.minecraft.item.EnumAction;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
@@ -243,10 +244,15 @@ public final class Spells {
|
||||
IForgeRegistry<Spell> registry = event.getRegistry();
|
||||
|
||||
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 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 SpellProjectile<>("thunderbolt", EntityThunderbolt::new).addProperties(Spell.DAMAGE, EntityThunderbolt.KNOCKBACK_STRENGTH).soundValues(0.8f, 0.9f, 0.2f));
|
||||
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 ShadowWard());
|
||||
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 Glide());
|
||||
registry.register(new SummonSpiritHorse());
|
||||
@@ -367,7 +373,7 @@ public final class Spells {
|
||||
registry.register(new Intimidate());
|
||||
registry.register(new Banish());
|
||||
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 PocketWorkbench());
|
||||
registry.register(new ImbueWeapon());
|
||||
|
||||
@@ -5,7 +5,6 @@ import electroblob.wizardry.constants.Tier;
|
||||
import electroblob.wizardry.loot.RandomSpell;
|
||||
import electroblob.wizardry.loot.WizardSpell;
|
||||
import electroblob.wizardry.spell.Spell;
|
||||
import net.minecraft.entity.EntityList;
|
||||
import net.minecraft.entity.EnumCreatureType;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.world.storage.loot.*;
|
||||
|
||||
@@ -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_HURT = createSound("entity.wizard.hurt");
|
||||
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_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_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){
|
||||
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.
|
||||
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.
|
||||
@@ -250,7 +258,7 @@ public final class WizardrySounds {
|
||||
event.getRegistry().register(MISC_PAGE_TURN);
|
||||
event.getRegistry().register(MISC_FREEZE);
|
||||
|
||||
for(Spell spell : Spell.getSpells(Spell.allSpells)){
|
||||
for(Spell spell : Spell.getAllSpells()){
|
||||
event.getRegistry().registerAll(spell.getSounds());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package electroblob.wizardry.spell;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.event.SpellCastEvent;
|
||||
import electroblob.wizardry.registry.WizardryItems;
|
||||
import electroblob.wizardry.registry.WizardryPotions;
|
||||
@@ -18,12 +19,21 @@ import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.event.entity.living.LivingEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
|
||||
import net.minecraftforge.fml.common.eventhandler.EventPriority;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
@Mod.EventBusSubscriber
|
||||
public class ArcaneJammer extends SpellRay {
|
||||
|
||||
private static final Field spellTicks;
|
||||
|
||||
static { // Yay more reflection
|
||||
spellTicks = ObfuscationReflectionHelper.findField(EntitySpellcasterIllager.class, "field_193087_b");
|
||||
}
|
||||
|
||||
public ArcaneJammer(){
|
||||
super("arcane_jammer", false, EnumAction.NONE);
|
||||
this.soundValues(0.7f, 1, 0.4f);
|
||||
@@ -68,9 +78,17 @@ public class ArcaneJammer extends SpellRay {
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onLivingUpdateEvent(LivingEvent.LivingUpdateEvent event){
|
||||
|
||||
if(event.getEntity() instanceof EntitySpellcasterIllager
|
||||
&& event.getEntityLiving().isPotionActive(WizardryPotions.arcane_jammer)){
|
||||
|
||||
((EntitySpellcasterIllager)event.getEntity()).setSpellType(EntitySpellcasterIllager.SpellType.NONE);
|
||||
|
||||
try{
|
||||
spellTicks.set(event.getEntity(), 10);
|
||||
}catch(IllegalAccessException e){
|
||||
Wizardry.logger.error("Error setting evoker spell timer:", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,11 +6,13 @@ import electroblob.wizardry.util.NBTExtras;
|
||||
import electroblob.wizardry.util.SpellModifiers;
|
||||
import electroblob.wizardry.util.WizardryUtilities;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.EnumAction;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityDispenser;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
@@ -32,9 +34,9 @@ public class ArcaneLock extends SpellRay {
|
||||
|
||||
@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
|
||||
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;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.registry.WizardryItems;
|
||||
import electroblob.wizardry.util.ParticleBuilder;
|
||||
import electroblob.wizardry.util.ParticleBuilder.Type;
|
||||
@@ -7,6 +8,7 @@ import electroblob.wizardry.util.SpellModifiers;
|
||||
import electroblob.wizardry.util.WizardryUtilities;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.EnumAction;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumParticleTypes;
|
||||
@@ -78,9 +80,7 @@ public class Banish extends SpellRay {
|
||||
world.rand.nextDouble() - 0.5, world.rand.nextDouble() - 0.5);
|
||||
}
|
||||
|
||||
// Can't be bothered to route this through the proxies!
|
||||
if(entity == net.minecraft.client.Minecraft.getMinecraft().player)
|
||||
electroblob.wizardry.client.WizardryClientEventHandler.playBlinkEffect();
|
||||
if(entity instanceof EntityPlayer) Wizardry.proxy.playBlinkEffect((EntityPlayer)entity);
|
||||
}
|
||||
|
||||
if(y != null){
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package electroblob.wizardry.spell;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.registry.WizardryItems;
|
||||
import electroblob.wizardry.util.RayTracer;
|
||||
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.rand.nextDouble() - 0.5, world.rand.nextDouble() - 0.5);
|
||||
}
|
||||
|
||||
// Can't be bothered to route this through the proxies!
|
||||
electroblob.wizardry.client.WizardryClientEventHandler.playBlinkEffect();
|
||||
|
||||
Wizardry.proxy.playBlinkEffect(caster);
|
||||
}
|
||||
|
||||
if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK){
|
||||
@@ -136,7 +136,7 @@ public class Blink extends Spell {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeCastByNPCs(){
|
||||
public boolean canBeCastBy(EntityLiving npc, boolean override){
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import electroblob.wizardry.registry.WizardryItems;
|
||||
import electroblob.wizardry.util.ParticleBuilder;
|
||||
import electroblob.wizardry.util.ParticleBuilder.Type;
|
||||
import electroblob.wizardry.util.SpellModifiers;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.entity.SharedMonsterAttributes;
|
||||
import net.minecraft.entity.monster.EntityZombie;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
@@ -21,6 +22,7 @@ import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.pathfinding.Path;
|
||||
import net.minecraft.pathfinding.PathNodeType;
|
||||
import net.minecraft.pathfinding.PathPoint;
|
||||
import net.minecraft.tileentity.TileEntityDispenser;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.TextComponentTranslation;
|
||||
@@ -44,8 +46,8 @@ public class Clairvoyance extends Spell {
|
||||
WizardData.registerStoredVariables(LOCATION_KEY, DIMENSION_KEY);
|
||||
}
|
||||
|
||||
@Override public boolean canBeCastByNPCs() { return false; }
|
||||
@Override public boolean canBeCastByDispensers() { return false; }
|
||||
@Override public boolean canBeCastBy(EntityLiving npc, boolean override) { return false; }
|
||||
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return false; }
|
||||
|
||||
@Override
|
||||
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 electroblob.wizardry.item.IConjuredItem;
|
||||
import electroblob.wizardry.registry.WizardryItems;
|
||||
import electroblob.wizardry.util.NBTExtras;
|
||||
import electroblob.wizardry.util.SpellModifiers;
|
||||
import electroblob.wizardry.util.WizardryUtilities;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
@@ -40,7 +41,7 @@ public class ConjureArmour extends SpellConjuration {
|
||||
armour = new ItemStack(SPECTRAL_ARMOUR_MAP.get(slot));
|
||||
IConjuredItem.setDurationMultiplier(armour, modifiers.get(WizardryItems.duration_upgrade));
|
||||
// Sets a blank "ench" tag to trick the renderer into showing the enchantment effect on the armour model
|
||||
armour.getTagCompound().setTag("ench", new NBTTagList());
|
||||
NBTExtras.storeTagSafely(armour.getTagCompound(), "ench", new NBTTagList());
|
||||
caster.setItemStackToSlot(slot, armour);
|
||||
flag = true;
|
||||
}
|
||||
|
||||
@@ -9,12 +9,14 @@ import electroblob.wizardry.registry.WizardrySounds;
|
||||
import electroblob.wizardry.util.*;
|
||||
import electroblob.wizardry.util.ParticleBuilder.Type;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.EnumAction;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.nbt.NBTUtil;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.tileentity.TileEntityDispenser;
|
||||
import net.minecraft.util.DamageSource;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
@@ -45,9 +47,9 @@ public class CurseOfSoulbinding extends SpellRay {
|
||||
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!
|
||||
@Override public boolean canBeCastByDispensers() { return false; }
|
||||
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return false; }
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@Override public boolean canBeCastByNPCs(){ return true; }
|
||||
@Override public boolean canBeCastBy(EntityLiving npc, boolean override){ return true; }
|
||||
|
||||
@Override
|
||||
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
||||
|
||||
@@ -85,7 +85,7 @@ public class DragonFireball extends Spell {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeCastByNPCs(){
|
||||
public boolean canBeCastBy(EntityLiving npc, boolean override){
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package electroblob.wizardry.spell;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.constants.Constants;
|
||||
import electroblob.wizardry.event.SpellCastEvent;
|
||||
import electroblob.wizardry.registry.WizardryItems;
|
||||
@@ -66,10 +67,16 @@ public class EmpoweringPresence extends Spell {
|
||||
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
|
||||
public static void onSpellCastPreEvent(SpellCastEvent.Pre event){
|
||||
// Empowerment stacks extra potency on top of the existing potency.
|
||||
if(event.getCaster() != null && event.getCaster().isPotionActive(WizardryPotions.empowerment)){
|
||||
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
|
||||
* (event.getCaster().getActivePotionEffect(WizardryPotions.empowerment).getAmplifier() + 1);
|
||||
@@ -78,4 +85,5 @@ public class EmpoweringPresence extends Spell {
|
||||
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.item.EnumAction;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.tileentity.TileEntityDispenser;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
@@ -29,8 +30,8 @@ public class ForestOfThorns extends Spell {
|
||||
}
|
||||
|
||||
@Override public boolean requiresPacket(){ return false; }
|
||||
@Override public boolean canBeCastByNPCs(){ return true; }
|
||||
@Override public boolean canBeCastByDispensers(){ return true; }
|
||||
@Override public boolean canBeCastBy(EntityLiving npc, boolean override){ return true; }
|
||||
@Override public boolean canBeCastBy(TileEntityDispenser dispenser){ return true; }
|
||||
|
||||
@Override
|
||||
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
|
||||
|
||||
@@ -11,6 +11,7 @@ public class FrostAxe extends SpellConjuration {
|
||||
|
||||
public FrostAxe(){
|
||||
super("frost_axe", WizardryItems.frost_axe);
|
||||
addProperties(DAMAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -9,7 +9,6 @@ import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.EnumAction;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.SoundEvent;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class Glide extends Spell {
|
||||
|
||||
@@ -19,6 +19,7 @@ import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.EnumAction;
|
||||
import net.minecraft.network.play.server.SPacketEntityVelocity;
|
||||
import net.minecraft.tileentity.TileEntityDispenser;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.SoundEvent;
|
||||
@@ -58,12 +59,12 @@ public class Grapple extends Spell {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeCastByNPCs(){
|
||||
return super.canBeCastByNPCs();
|
||||
public boolean canBeCastBy(EntityLiving npc, boolean override){
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeCastByDispensers(){
|
||||
public boolean canBeCastBy(TileEntityDispenser dispenser){
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,14 @@ import electroblob.wizardry.util.ParticleBuilder.Type;
|
||||
import electroblob.wizardry.util.SpellModifiers;
|
||||
import electroblob.wizardry.util.WizardryUtilities;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.item.EntityTNTPrimed;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.item.EnumAction;
|
||||
import net.minecraft.network.play.server.SPacketEntityVelocity;
|
||||
import net.minecraft.tileentity.TileEntityDispenser;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.SoundEvent;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
@@ -41,8 +43,8 @@ public class GreaterTelekinesis extends SpellRay {
|
||||
this.soundValues(0.8f, 1, 0.2f);
|
||||
}
|
||||
|
||||
@Override public boolean canBeCastByNPCs() { return false; }
|
||||
@Override public boolean canBeCastByDispensers() { return false; }
|
||||
@Override public boolean canBeCastBy(EntityLiving npc, boolean override) { return false; }
|
||||
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return false; }
|
||||
|
||||
@Override
|
||||
protected SoundEvent[] createSounds(){
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package electroblob.wizardry.spell;
|
||||
|
||||
import electroblob.wizardry.Wizardry;
|
||||
import electroblob.wizardry.registry.WizardryItems;
|
||||
import electroblob.wizardry.util.AllyDesignationSystem;
|
||||
import electroblob.wizardry.util.ParticleBuilder;
|
||||
@@ -62,4 +63,9 @@ public class InvigoratingPresence extends Spell {
|
||||
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.WizardryUtilities;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.monster.*;
|
||||
import net.minecraft.entity.passive.*;
|
||||
@@ -52,7 +53,7 @@ public class Metamorphosis extends SpellRay {
|
||||
this.soundValues(0.5f, 1f, 0);
|
||||
}
|
||||
|
||||
@Override public boolean canBeCastByNPCs() { return false; }
|
||||
@Override public boolean canBeCastBy(EntityLiving npc, boolean override) { return false; }
|
||||
|
||||
@Override
|
||||
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.nbt.NBTTagCompound;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.tileentity.TileEntityDispenser;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
@@ -43,8 +44,8 @@ public class MindControl extends SpellRay {
|
||||
addProperties(EFFECT_DURATION);
|
||||
}
|
||||
|
||||
@Override public boolean canBeCastByNPCs() { return false; }
|
||||
@Override public boolean canBeCastByDispensers() { return false; }
|
||||
@Override public boolean canBeCastBy(EntityLiving npc, boolean override) { return false; }
|
||||
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return false; }
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
// Can't be bothered to route this through the proxies!
|
||||
electroblob.wizardry.client.WizardryClientEventHandler.playBlinkEffect();
|
||||
Wizardry.proxy.playBlinkEffect(caster);
|
||||
}
|
||||
|
||||
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.WizardryUtilities;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.MobEffects;
|
||||
@@ -28,7 +29,7 @@ public class Poison extends SpellRay {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeCastByNPCs(){
|
||||
public boolean canBeCastBy(EntityLiving npc, boolean override){
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import electroblob.wizardry.packet.PacketPossession;
|
||||
import electroblob.wizardry.packet.WizardryPacketHandler;
|
||||
import electroblob.wizardry.registry.Spells;
|
||||
import electroblob.wizardry.registry.WizardryItems;
|
||||
import electroblob.wizardry.util.NBTExtras;
|
||||
import electroblob.wizardry.util.ParticleBuilder;
|
||||
import electroblob.wizardry.util.ParticleBuilder.Type;
|
||||
import electroblob.wizardry.util.SpellModifiers;
|
||||
@@ -43,6 +44,7 @@ import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.potion.PotionEffect;
|
||||
import net.minecraft.potion.PotionUtils;
|
||||
import net.minecraft.tileentity.TileEntityDispenser;
|
||||
import net.minecraft.util.*;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
@@ -123,8 +125,8 @@ public class Possession extends SpellRay {
|
||||
addProperties(EFFECT_DURATION, CRITICAL_HEALTH);
|
||||
}
|
||||
|
||||
@Override public boolean canBeCastByNPCs() { return false; }
|
||||
@Override public boolean canBeCastByDispensers() { return false; }
|
||||
@Override public boolean canBeCastBy(EntityLiving npc, boolean override) { return false; }
|
||||
@Override public boolean canBeCastBy(TileEntityDispenser dispenser) { return false; }
|
||||
|
||||
@Override
|
||||
public boolean requiresPacket(){
|
||||
@@ -267,7 +269,7 @@ public class Possession extends SpellRay {
|
||||
// Inventory and items
|
||||
|
||||
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();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package electroblob.wizardry.spell;
|
||||
|
||||
import electroblob.wizardry.util.SpellModifiers;
|
||||
import net.minecraft.entity.EntityLiving;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.util.EnumHand;
|
||||
@@ -17,7 +18,7 @@ public class ReplenishHunger extends SpellBuff {
|
||||
addProperties(HUNGER_POINTS, SATURATION_MODIFIER);
|
||||
}
|
||||
|
||||
@Override public boolean canBeCastByNPCs(){ return false; }
|
||||
@Override public boolean canBeCastBy(EntityLiving npc, boolean override){ return false; }
|
||||
|
||||
@Override
|
||||
protected boolean applyEffects(EntityLivingBase caster, SpellModifiers modifiers){
|
||||
|
||||
@@ -25,6 +25,8 @@ public class Resurrection extends Spell {
|
||||
|
||||
public static final String WAIT_TIME = "wait_time";
|
||||
|
||||
private static final String POTION_CORE_FIX_NBT_KEY = "Potion Core - Health Fix";
|
||||
|
||||
public Resurrection(){
|
||||
super("resurrection", EnumAction.NONE, false);
|
||||
addProperties(EFFECT_RADIUS, WAIT_TIME);
|
||||
@@ -90,6 +92,8 @@ public class Resurrection extends Spell {
|
||||
player.experience = 0;
|
||||
player.experienceLevel = 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){
|
||||
ParticleBuilder.spawnHealParticles(player.world, player);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user