Compare commits

..

83 Commits

Author SHA1 Message Date
Electroblob77 51a2ff0976 Update version number 2019-01-04 22:12:37 +00:00
Electroblob77 1b298ff18b Update credits (all locations) 2019-01-04 22:12:06 +00:00
Electroblob77 86d13d3a6e Swap canSnowAt for canPlaceBlockAt, so it actually works... 2019-01-04 21:58:45 +00:00
Electroblob77 5421372754 Unike input events, tick events fire before the player is initialised, so add a check to stop it crashing with an NPE. 2019-01-04 21:53:39 +00:00
Electroblob77 53b29939f1 Change key handler to listen for ClientTickEvent instead of KeyInputEvent, swap isPressed() to isKeyDown() and restructure code; fixes 'lag'/inconsistent behaviour with mouse button keybinds. (See also #79, not sure if this fixes it since I can't reproduce the problem.) 2019-01-04 21:48:35 +00:00
Electroblob77 7bda8db86f Add check for wand before sending control packets, prevents unnecessary packets being sent 2019-01-04 21:04:06 +00:00
Electroblob77 a7a48cd32b Add a less than max timer check so that magic light does not keep growing indefinitely if the block fails to disappear. Helps reduce the effects of #101 but does not fix it. 2019-01-04 20:53:01 +00:00
Electroblob77 b8e0836a6d Add test for fake players in retaliatory ice shroud effect, fixes #93 2019-01-04 20:48:03 +00:00
Electroblob77 a7e6b2892c Add check to prevent ArrayIndexOutOfBoundsException in WandHelper, fixes #90 (and duplicate issues #80, #91, #97 and #98) 2019-01-04 20:07:02 +00:00
Electroblob77 f886ebfd75 Prevent ice age from placing snow layers at invalid locations, fixes #64 2019-01-04 20:05:09 +00:00
Electroblob77 98b334e6d7 Add condition to only write magic projectile thrower to spawn data if the thrower exists and tweak overrides so it is always written/read last, fixes #71 2019-01-04 20:04:43 +00:00
Electroblob77 83edb8007e Replace direct translation in /allies command with text component, fixes #70 2019-01-04 20:02:57 +00:00
Electroblob77 67dda448f3 Add background tint to arcane workbench GUI, fixes #96 2019-01-04 19:58:31 +00:00
Electroblob77 09953c0299 Add bottom of world check to wizard tower foundation worldgen, fixes #73 2019-01-04 19:57:33 +00:00
Electroblob77 38b0fa65bc Comment out scroll translation console message, fixes #56 2019-01-04 19:56:39 +00:00
Electroblob 7200182c82 Merge pull request #102 from dragon-evol/1.12.2
[zh_cn_handbook update]minor, minor, minor fixes (sorry for disturbing...)
2019-01-03 23:08:10 +00:00
dragon-evol e73e998de2 minor fixes 2019-01-03 13:19:53 +08:00
Electroblob a69da2eb2a Merge pull request #94 from dragon-evol/1.12.2
Update zh_cn.lang and translate the handbook
2018-12-18 00:23:36 +00:00
dragon-evol a00c594d83 Add files via upload 2018-12-17 14:23:23 +08:00
dragon-evol 3df99552e1 Merge pull request #1 from dragon-evol/dragon-evol-patch-1
Update zh_cn.lang
2018-12-17 14:22:20 +08:00
dragon-evol e2bc2824f6 Add files via upload 2018-12-17 14:11:18 +08:00
Electroblob 36f4728f3a Merge pull request #88 from Avatair/feature/mapping-update
Updated MCP Mapping to stable39
2018-11-24 18:20:08 +00:00
alesto 6ca72e7965 Undid adding wizardry dependency. 2018-11-24 09:56:35 +01:00
alesto 151dcc06da Updated mappings 2018-11-22 16:02:40 +01:00
Electroblob 5737109dec Merge pull request #82 from HellFirePvP/1.12.2
Switch enchantment-writing related code to a more direct data-driven approach
2018-11-10 00:48:16 +00:00
HellFirePvP 4bd3a46f32 Switch enchantment-writing related code to a more direct data-driven approach 2018-11-01 13:19:46 +01:00
Electroblob 73e2d64fcd Update guide_for_contributing.md 2018-08-17 23:06:46 +01:00
Electroblob 1f008b405d Update ISSUE_TEMPLATE.md 2018-08-01 23:13:43 +01:00
Electroblob 00e1e2602f Update guide_for_contributing.md 2018-08-01 23:11:27 +01:00
Electroblob 98445da971 Update ISSUE_TEMPLATE.md 2018-08-01 22:59:42 +01:00
Electroblob dbc1490e10 Merge pull request #53 from ZHENGLOC/1.12.2
Update zh_cn.lang
2018-06-17 11:21:23 +01:00
ZLOCK_1911 f33a0aceb2 Update zh_cn.lang 2018-06-09 12:02:45 +08:00
Electroblob 7141ae9544 Update CREDITS.md 2018-06-07 17:34:36 +01:00
Electroblob af638ab2f7 Merge pull request #51 from ZHENGLOC/1.12.2
Create zh_cn.lang
2018-06-07 17:32:32 +01:00
ZLOCK_1911 a75a6c6114 Create zh_cn.lang 2018-06-07 18:31:37 +08:00
Electroblob 9c1042f686 Update version number 2018-06-05 17:01:04 +01:00
Electroblob cad3fee1b9 Update mcmod.info 2018-06-05 16:58:33 +01:00
Electroblob 5947b2ee62 Fix smoke bomb recipe and allow charcoal to be used 2018-06-05 16:00:47 +01:00
Electroblob 177a39bad1 Cleanup 2018-06-05 15:43:56 +01:00
Electroblob cdf8f6e32d Remove now-redundant recipe config options 2018-06-05 15:43:48 +01:00
Electroblob f88aac11e9 Convert all non-dynamic recipes to JSON, add ore dictionary support where appropriate and change incorrect "amount" tag to "count", fixes #18 2018-06-05 15:43:14 +01:00
Electroblob 05b905b988 Fix light level detection for petrified creatures breaking out 2018-06-05 14:12:33 +01:00
Electroblob 669cd2892d Add check for valid special wand upgrades, fixes #48 2018-06-05 11:12:03 +01:00
Electroblob dd07d08ff0 Return true in ADS methods when passed a null attacker, acting as a fallback for when caster does not save properly; fixes #40 2018-06-04 23:45:10 +01:00
Electroblob 54bb327fdf Properly sync thrower field for all throwable projectiles, fixes #42 (does not fix vanilla throwables though) 2018-06-04 23:42:12 +01:00
Electroblob 2cd8b46c1f Add toughness to legendary wizard armour 2018-06-04 18:32:32 +01:00
Electroblob b61413f7f1 Remove ISpecialArmor from ItemWizardArmour since it is no longer necessary, fixes #44 2018-06-04 18:20:55 +01:00
Electroblob 4e7765a7e7 Allow tab-completion of spell names in commands without specifying the modid 2018-06-04 18:04:36 +01:00
Electroblob 49a6dc43c1 Cleanup 2018-06-04 17:20:39 +01:00
Electroblob b82bc6698f Make crystal ore drop xp when mined 2018-06-04 17:17:58 +01:00
Electroblob 1e43c67660 Tweak summoned creature targeting so that non-evil wizards' minions no longer attack players unless the player in question has angered the wizard 2018-06-04 17:17:33 +01:00
Electroblob c129571167 Change EntityWizard to implement IMerchant and INpc directly rather than extending EntityVillager, fixes #38 plus a number of other bugs 2018-06-04 16:36:20 +01:00
Electroblob b23a643c0e Make arcane workbench drop items correctly when broken, fixes #20 2018-06-04 15:00:02 +01:00
Electroblob 194bff3e6a Miscellaneous lang file fixes 2018-06-04 13:09:23 +01:00
Electroblob 426ca78288 Sort config options into a more logical order 2018-06-04 12:51:12 +01:00
Electroblob f15919fdce Organise the config file and GUI into categories 2018-06-04 12:39:56 +01:00
Electroblob 2124842136 Fix transportation stone not dropping when unsupported, fixes #23 2018-06-03 23:57:22 +01:00
Electroblob 70e697876b Centralise code for config GUI category classes 2018-06-03 23:24:42 +01:00
Electroblob 9b5e5a871c Add dimension whitelist option for evil wizard spawning and restrict numbers to 1 per chunk, closes #26 2018-06-03 22:22:18 +01:00
Electroblob 5ba92e5de5 Change whitelist/blacklist storage from strings to resourcelocations to bring it in line with the registry system 2018-06-03 22:17:57 +01:00
Electroblob 4e6780a3cf Replace getEntityString with getKey(...).toString() 2018-06-03 18:19:10 +01:00
Electroblob 00584ad635 Move resistances config setup from preInit to init 2018-06-03 18:18:29 +01:00
Electroblob f72ed33515 Add mind control targets blacklist config option 2018-06-03 18:17:05 +01:00
Electroblob c2366ed1ba Change crystal ore drop quantity to drop the intended 1-3 crystals (rather than the previous 1-2) and change fortune behaviour to work like vanilla ores, see discussion in #43 2018-06-03 15:52:13 +01:00
Electroblob 46df8d7311 Add smelting recipe for crystal ore, closes #43 2018-06-03 15:15:50 +01:00
Electroblob d4579b9184 Remove all calls to GlStateManager.pushAttrib() and pullAttrib() and a few other tweaks to gl calls, fixes #12, #46 and #47 2018-06-03 12:39:25 +01:00
Electroblob ee6f0cfe70 Correct death message lang key in code, fixes #41 2018-06-02 16:08:48 +01:00
Electroblob 6155fd9c68 Display non-keyboard keybinds correctly, fixes #36 2018-06-02 15:14:32 +01:00
Electroblob 32c0608b51 Stop spirit horses dropping leather, fixes #37. Also adds the same overrides to spirit wolves; since regular wolves don't drop anything this wasn't noticeable. 2018-06-02 13:39:21 +01:00
Electroblob 404df6af23 Fixes #32 2018-06-02 13:35:37 +01:00
Electroblob 764e10538b Update LICENSE.md 2018-05-21 10:45:11 +01:00
Electroblob 6b1b590e30 Merge pull request #25 from Shadows-of-Fire/client
Fixes #17, #22, and maybe #12
2018-05-04 19:50:11 +01:00
Shadows_of_Fire 8360e520cd De-duplicate armor value 2018-05-04 14:34:09 -04:00
Shadows_of_Fire 005a17d750 Fix armor value tooltips 2018-05-04 14:23:57 -04:00
Shadows_of_Fire 28abe036a0 Armor properly has 0 damage reduction when oom
tooltip is being buggy, won't display armor reduction values.
2018-05-04 08:18:15 -04:00
Shadows_of_Fire ca96112b67 Fix wizard armor breaking 2018-05-04 07:35:51 -04:00
Shadows_of_Fire b8e847c6a6 Fixes #22 2018-05-04 06:53:11 -04:00
Shadows_of_Fire 35cb2c31fc Convert to GlStateManager calls
also removes the weird reflection being used to access the RenderItem
2018-05-04 06:45:57 -04:00
Electroblob 30dd587d34 Move wiki resources to wiki git repository 2018-05-03 20:47:46 +01:00
Electroblob 4644814582 Add wiki resources 2018-05-03 20:31:25 +01:00
Electroblob 7db3151d8a Change hardness of transportation to 0.3, fixes #19 2018-05-02 18:23:07 +01:00
Electroblob c8ca73cca9 Fix incorrect event handler annotation 2018-05-02 13:35:47 +01:00
Electroblob d5a0479ebe Update .gitignore 2018-05-02 13:19:30 +01:00
76 changed files with 2128 additions and 854 deletions
+1
View File
@@ -21,4 +21,5 @@ build
eclipse
run
misc
libs
Thumbs.db
+4 -1
View File
@@ -1,7 +1,7 @@
# Credits
Electroblob's Wizardry
Version 4.1.0
Version 4.1.3
For Minecraft 1.12.2
Designed, coded and textured by Electroblob
@@ -16,10 +16,13 @@ In addition, I'd like to thank the following individuals for their contributions
- Corail31
- 12foo
- Shadows-of-Fire
- HellFirePvP
#### Translations
- Russian: VilagVil
- Spanish and Mexican Spanish: MadWrist
- Chinese: ZHENGLOC and dragon-evol
Lightning ray sound effect from OhhWowProductions
+4 -2
View File
@@ -1,5 +1,7 @@
Minecraft version: 1.10.2 [change as necessary]
Wizardry version: 2.1.0 [change as necessary]
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.3 [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.]
+2 -2
View File
@@ -1,7 +1,7 @@
# License
This repository is copyright © Electroblob 2018. The following license is provided to allow you to creatively contribute to and improve the repository.
This license applies only to the source code and assets present in this repository. The compiled mod (available at https://minecraft.curseforge.com/projects/electroblobs-wizardry) comes under its own separate license, see the aforementioned webpage for details.
This license applies only to the source code, assets and wiki pages present in this repository. The compiled mod (available at https://minecraft.curseforge.com/projects/electroblobs-wizardry) comes under its own separate license, see the aforementioned webpage for details.
TL;DR: Do what you want with this repo on Github, but ask me first if you want to put it anywhere else or publish your version. Don't try and make money off the repo or anything in it. I'm not responsible if the code breaks things, and if you help me out by submitting a PR, I can use and modify the contents of that PR as long as I give you credit. (This brief summary is non-binding and does not override or replace the full license below.)
@@ -17,7 +17,7 @@ TL;DR: Do what you want with this repo on Github, but ask me first if you want t
'Electroblob's Wizardry', 'Wizardry', 'the mod' - The Minecraft modification Electroblob's Wizardry
'Repository' - This repository on Github, containing this license, other informational files, configurations, code and assets which are part of Electroblob's Wizardry
'Repository' - This repository on Github, containing this license, the wiki, other informational files, configurations, code and assets which are part of Electroblob's Wizardry
'Curseforge' - The webpage https://minecraft.curseforge.com/projects/electroblobs-wizardry
+2 -2
View File
@@ -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.1.1 - MC 1.12.2"
version = " 4.1.3 - MC 1.12.2"
group= "electroblob.wizardry"// http://maven.apache.org/guides/mini/guide-naming-conventions.html
archivesBaseName = "Electroblob's Wizardry "
@@ -29,7 +29,7 @@ minecraft {
// stable_# stables are built at the discretion of the MCP team.
// Use non-default mappings at your own risk. they may not always work.
// simply re-run your setup task after changing the mappings to update your workspace.
mappings = "snapshot_20180316"
mappings = "stable_39"
// makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
}
+14 -1
View File
@@ -2,7 +2,20 @@
## Submitting an issue
When submitting an issue, please stick to the issue template. Please give me as much information about the issue as you can, but keep it relevant. "This is really annoying me and my friend" does not help me fix the problem! Most importantly, use gist or pastebin to post crash reports.
When submitting an issue, I would be grateful if you could follow these few guidelines:
- First and foremost, please check your issue hasn't already been posted. The issue tracker is searchable, so try typing in a few keywords and see if anything comes up.
- Please stick to the issue template, it's there to help you provide the right information so I can fix the problem more easily. If you're not sure what to put for anything, that's ok, just leave it as it is.
- Please give me as much information about the issue as you can, but keep it relevant. "This is really annoying me and my friend" does not help me fix the problem!
- There's no need to put 'tags' in square brackets in the issue title, I'll put proper github issue tags on it which will also help organise it. You can use them to search for issues too!
- Don't close an issue unless it has actually been fixed or is no longer relevant - otherwise I might not end up fixing it at all! Usually I'll take care of closing issues anyway, so you don't have to worry about it.
- Most importantly, use gist or pastebin to post crash reports. Do not paste the entire crash report inline, not even in a code block!
> If you've got a git account (which you do, if you're posting an issue) you can access gist, and pastebin doesn't require an account at all, so there's no excuse!
## Submitting a PR
@@ -143,8 +143,9 @@ public class CommonProxy {
// I have now learnt that the server side I18n always translates to the default en_US, so I could just return
// a hardcoded name in English instead.
Wizardry.logger.info("A mod has called ItemScroll#getItemStackDisplayName from the server side. Using the"
+ "deprecated server-side translation methods as a fallback.");
// Commented because it's just really annoying.
//Wizardry.logger.info("A mod has called ItemScroll#getItemStackDisplayName from the server side. Using the"
// + "deprecated server-side translation methods as a fallback.");
// Displays [Empty slot] if spell is continuous.
Spell spell = Spell.get(scroll.getItemDamage());
+201 -197
View File
@@ -1,6 +1,7 @@
package electroblob.wizardry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
@@ -45,9 +46,8 @@ import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
* @since Wizardry 1.2
* @author Electroblob
*/
// NOTE: We could convert over to the @Config system IF it is sufficiently complete in this Forge version for my
// purposes.
// (For one, I know that the LangKey annotation is not applicable to type declarations in 1.10.2, unlike in 1.11.2)
// TODO: New plan: convert to the @Config system BUT separate the spells config out so it doesn't break stuff. (Maybe even
// make it a JSON instead? Either way, there's scope for then adding more options for adjusting the base attributes etc.)
// @Config(modid = Wizardry.MODID)
@SuppressWarnings("deprecation") // Used server I18n deliberately; we want to write the comments in english.
public final class Settings {
@@ -63,8 +63,8 @@ public final class Settings {
public static final String COMMANDS_CATEGORY = "commands";
/** The unlocalised name of the worldgen config category. */
public static final String WORLDGEN_CATEGORY = "worldgen";
/** The unlocalised name of the global config category. */
public static final String GLOBAL_CATEGORY = "global";
/** The unlocalised name of the gameplay config category. */
public static final String GAMEPLAY_CATEGORY = "gameplay";
/** The wizardry config file. */
private Configuration config;
@@ -102,19 +102,26 @@ public final class Settings {
/** <b>[Server-only]</b> Whether summoned creatures can revenge attack their caster if their caster attacks them. */
public boolean minionRevengeTargeting = true;
/**
* <b>[Server-only]</b> List of names of entities which summoned creatures are allowed to attack, in addition to the
* defaults.
* <b>[Server-only]</b> List of registry names of entities which summoned creatures are allowed to attack, in addition
* to the defaults.
*/
public String[] summonedCreatureTargetsWhitelist = {};
public ResourceLocation[] summonedCreatureTargetsWhitelist = {};
/**
* <b>[Server-only]</b> List of names of entities which summoned creatures are specifically not allowed to attack,
* overriding the defaults and the whitelist.
* <b>[Server-only]</b> List of registry names of entities which summoned creatures are specifically not allowed to
* attack, overriding the defaults and the whitelist.
*/
public String[] summonedCreatureTargetsBlacklist = {"creeper"};
public ResourceLocation[] summonedCreatureTargetsBlacklist = {new ResourceLocation("creeper")};
/**
* <b>[Server-only]</b> List of registry names of entities which are immune to the mind control spell, in addition to
* the defaults.
*/
public ResourceLocation[] mindControlTargetsBlacklist = {};
/** <b>[Server-only]</b> Global damage scaling factor for all player magic damage. */
public double playerDamageScale = 1.0f;
/** <b>[Server-only]</b> Global damage scaling factor for all npc magic damage. */
public double npcDamageScale = 1.0f;
/** <b>[Server-only]</b> List of dimension ids in which evil wizards can spawn. */
public int[] evilWizardDimensions = {0};
// Commands (these don't need synchronising since typing a command always queries the server).
/**
@@ -134,19 +141,6 @@ public final class Settings {
// Synchronised settings. These settings affect both client-side AND server-side code. Changing these locally
// only has an effect if the local game is the host, i.e. a dedicated server, a LAN host or a singleplayer world.
// Recipes (only need syncing for display in the wizard's handbook)
/** <b>[Synchronised]</b> Whether or not firebombs should be craftable. */
public boolean firebombIsCraftable = true;
/** <b>[Synchronised]</b> Whether or not poison bombs should be craftable. */
public boolean poisonBombIsCraftable = true;
/** <b>[Synchronised]</b> Whether or not poison bombs should be craftable. */
public boolean smokeBombIsCraftable = true;
/**
* <b>[Synchronised]</b> Whether to require a magic crystal in the blank scroll crafting recipe (in case it
* conflicts with another mod).
*/
public boolean useAlternateScrollRecipe = false;
// Gamemodes
/**
* <b>[Synchronised]</b> When set to true, spells a player hasn't cast yet will be unreadable until they are cast
@@ -218,7 +212,7 @@ public final class Settings {
/**
* Called from preInit to initialise the config file. The first part of the config file has to be done here (as is
* conventional) so that the various registries can change what they do accordingly. The spell part of the config
* has to be done in the init method.
* and the resistance part of the config have to be done in the init method since they depend on the registry events.
*/
void initConfig(FMLPreInitializationEvent event){
@@ -228,20 +222,27 @@ public final class Settings {
Wizardry.logger.info("Setting up main config");
setupGeneralConfig();
setupWorldgenConfig();
setupClientConfig();
setupCommandsConfig();
config.save();
}
/**
* Called from init to initialise the parts of the config file that depend on other mods. For example, the spell
* config is done here and not in preInit because all spells must be registered before it is added, including those
* in other mods.
* Called from init to initialise the parts of the config file that have to be done after registry events are fired.
* For example, the spell config is done here and not in preInit because all spells must be registered before it is
* added, including those in other mods.
*/
void initConfigExtras(){
Wizardry.logger.info("Setting up spells config for " + Spell.getTotalSpellCount() + " spells");
setupSpellsConfig();
Wizardry.logger.info("Setting up resistances config");
setupResistancesConfig();
config.save();
}
@@ -252,7 +253,11 @@ public final class Settings {
Wizardry.logger.info("Saving in-game config changes");
setupGeneralConfig();
setupWorldgenConfig();
setupClientConfig();
setupCommandsConfig();
setupSpellsConfig();
setupResistancesConfig();
config.save();
}
@@ -292,19 +297,22 @@ public final class Settings {
Property property;
config.addCustomCategoryComment(Configuration.CATEGORY_GENERAL,
"Please note that changing some of these settings may make the mod very difficult to play.");
config.addCustomCategoryComment(GAMEPLAY_CATEGORY, "Global settings that affect game mechanics. In multiplayer, the server/LAN host settings will apply. Please note that changing some of these settings may make the mod very difficult to play.");
property = config.get(Configuration.CATEGORY_GENERAL, "towerRarity", 8,
"Rarity of wizard towers. Higher numbers are rarer. Set to 0 to disable wizard towers completely.", 0,
50);
property.setLanguageKey("config." + Wizardry.MODID + ".tower_rarity");
property = config.get(GAMEPLAY_CATEGORY, "discoveryMode", true,
"For those who like a sense of mystery! When set to true, spells you haven't cast yet will be unreadable until you cast them (on a per-world basis). Has no effect when in creative mode. Spells of identification will be unobtainable in survival mode if this is false.");
property.setLanguageKey("config." + Wizardry.MODID + ".discovery_mode");
property.setRequiresWorldRestart(true);
Wizardry.proxy.setToNumberSliderEntry(property);
towerRarity = property.getInt();
discoveryMode = property.getBoolean();
propOrder.add(property.getName());
property = config.get(Configuration.CATEGORY_GENERAL, "spellBookDropChance", 3,
property = config.get(GAMEPLAY_CATEGORY, "friendlyFire", true,
"Whether to allow players to damage their designated allies using magic.");
property.setLanguageKey("config." + Wizardry.MODID + ".friendly_fire");
friendlyFire = property.getBoolean();
propOrder.add(property.getName());
property = config.get(GAMEPLAY_CATEGORY, "spellBookDropChance", 3,
"The chance for mobs to drop a spell book when killed. The greater this number, the more often they will drop. Set to 0 to disable spell book drops. Set to 200 for guaranteed drops.",
0, 200);
property.setLanguageKey("config." + Wizardry.MODID + ".spell_book_drop_chance");
@@ -312,202 +320,208 @@ public final class Settings {
spellBookDropChance = property.getInt();
propOrder.add(property.getName());
property = config.get(Configuration.CATEGORY_GENERAL, "oreDimensions", new int[]{0},
"List of dimension ids in which crystal ore will generate. Note that removing the overworld (id 0) from this list will make the mod VERY difficult to play!");
property.setLanguageKey("config." + Wizardry.MODID + ".ore_dimensions");
property.setRequiresWorldRestart(true);
oreDimensions = property.getIntList();
propOrder.add(property.getName());
property = config.get(Configuration.CATEGORY_GENERAL, "flowerDimensions", new int[]{0},
"List of dimension ids in which crystal flowers will generate.");
property.setLanguageKey("config." + Wizardry.MODID + ".flower_dimensions");
property.setRequiresWorldRestart(true);
flowerDimensions = property.getIntList();
propOrder.add(property.getName());
property = config.get(Configuration.CATEGORY_GENERAL, "towerDimensions", new int[]{0},
"List of dimension ids in which wizard towers will generate.");
property.setLanguageKey("config." + Wizardry.MODID + ".tower_dimensions");
property.setRequiresWorldRestart(true);
towerDimensions = property.getIntList();
propOrder.add(property.getName());
property = config.get(Configuration.CATEGORY_GENERAL, "generateLoot", true,
"Whether to generate wizardry loot in dungeon chests.");
property.setLanguageKey("config." + Wizardry.MODID + ".generate_loot");
property.setRequiresWorldRestart(true);
generateLoot = property.getBoolean();
propOrder.add(property.getName());
property = config.get(Configuration.CATEGORY_GENERAL, "firebombIsCraftable", true,
"Whether firebombs can be crafted or not.");
property.setLanguageKey("config." + Wizardry.MODID + ".firebomb_is_craftable");
property = config.get(GAMEPLAY_CATEGORY, "evilWizardDimensions", new int[]{0},
"List of dimension ids in which evil wizards can spawn.");
property.setLanguageKey("config." + Wizardry.MODID + ".evil_wizard_dimensions");
property.setRequiresMcRestart(true);
firebombIsCraftable = property.getBoolean();
evilWizardDimensions = property.getIntList();
propOrder.add(property.getName());
property = config.get(Configuration.CATEGORY_GENERAL, "poisonBombIsCraftable", true,
"Whether poison bombs can be crafted or not.");
property.setLanguageKey("config." + Wizardry.MODID + ".poison_bomb_is_craftable");
property.setRequiresMcRestart(true);
poisonBombIsCraftable = property.getBoolean();
// These two aren't sliders because using a slider makes it difficult to fine-tune the numbers; the nature of a
// scaling factor means that 0.5 is as big a change as 2.0, so whilst a slider is fine for increasing the
// damage, it doesn't give fine enough control for values less than 1.
property = config.get(GAMEPLAY_CATEGORY, "playerDamageScaling", 1.0,
"Global damage scaling factor for the damage dealt by players casting spells, relative to 1.", 0, 20);
property.setLanguageKey("config." + Wizardry.MODID + ".player_damage_scaling");
playerDamageScale = property.getDouble();
propOrder.add(property.getName());
property = config.get(Configuration.CATEGORY_GENERAL, "smokeBombIsCraftable", true,
"Whether smoke bombs can be crafted or not.");
property.setLanguageKey("config." + Wizardry.MODID + ".smoke_bomb_is_craftable");
property.setRequiresMcRestart(true);
smokeBombIsCraftable = property.getBoolean();
property = config.get(GAMEPLAY_CATEGORY, "npcDamageScaling", 1.0,
"Global damage scaling factor for the damage dealt by NPCs casting spells, relative to 1.", 0, 20);
property.setLanguageKey("config." + Wizardry.MODID + ".npc_damage_scaling");
npcDamageScale = property.getDouble();
propOrder.add(property.getName());
property = config.get(Configuration.CATEGORY_GENERAL, "useAlternateScrollRecipe", false,
"Whether to require a magic crystal in the shapeless crafting recipe for blank scrolls. Set to true if another mod adds a conflicting recipe.");
property.setLanguageKey("config." + Wizardry.MODID + ".use_alternate_scroll_recipe");
property.setRequiresMcRestart(true);
useAlternateScrollRecipe = property.getBoolean();
propOrder.add(property.getName());
property = config.get(Configuration.CATEGORY_GENERAL, "teleportThroughUnbreakableBlocks", false,
"Whether players are allowed to teleport through unbreakable blocks (e.g. bedrock) using the phase step spell.");
property.setLanguageKey("config." + Wizardry.MODID + ".teleport_through_unbreakable_blocks");
teleportThroughUnbreakableBlocks = property.getBoolean();
propOrder.add(property.getName());
property = config.get(Configuration.CATEGORY_GENERAL, "showSummonedCreatureNames", true,
"Whether to show summoned creatures' names and owners above their heads.");
property.setLanguageKey("config." + Wizardry.MODID + ".show_summoned_creature_names");
showSummonedCreatureNames = property.getBoolean();
propOrder.add(property.getName());
property = config.get(Configuration.CATEGORY_GENERAL, "friendlyFire", true,
"Whether to allow players to damage their designated allies using magic.");
property.setLanguageKey("config." + Wizardry.MODID + ".friendly_fire");
friendlyFire = property.getBoolean();
propOrder.add(property.getName());
property = config.get(Configuration.CATEGORY_GENERAL, "telekineticDisarmament", true,
"Whether to allow players to disarm other players using the telekinesis spell. Set to false to prevent stealing of items.");
property.setLanguageKey("config." + Wizardry.MODID + ".telekinetic_disarmament");
telekineticDisarmament = property.getBoolean();
propOrder.add(property.getName());
property = config.get(Configuration.CATEGORY_GENERAL, "discoveryMode", true,
"For those who like a sense of mystery! When set to true, spells you haven't cast yet will be unreadable until you cast them (on a per-world basis). Has no effect when in creative mode. Spells of identification will be unobtainable in survival mode if this is false.");
property.setLanguageKey("config." + Wizardry.MODID + ".discovery_mode");
property.setRequiresWorldRestart(true);
discoveryMode = property.getBoolean();
propOrder.add(property.getName());
property = config.get(Configuration.CATEGORY_GENERAL, "enableShiftScrolling", true,
"Whether you can switch between spells on a wand by scrolling with the mouse wheel while sneaking. Note that this will only affect you; other players connected to the same server obey their own settings.");
property.setLanguageKey("config." + Wizardry.MODID + ".enable_shift_scrolling");
property.setRequiresWorldRestart(false);
enableShiftScrolling = property.getBoolean();
propOrder.add(property.getName());
property = config.get(Configuration.CATEGORY_GENERAL, "minionRevengeTargeting", true,
property = config.get(GAMEPLAY_CATEGORY, "minionRevengeTargeting", true,
"Whether summoned creatures can revenge attack their owner if their owner attacks them.");
property.setLanguageKey("config." + Wizardry.MODID + ".minion_revenge_targeting");
property.setRequiresWorldRestart(false);
minionRevengeTargeting = property.getBoolean();
propOrder.add(property.getName());
// These two aren't sliders because using a slider makes it difficult to fine-tune the numbers; the nature of a
// scaling factor means that 0.5 is as big a change as 2.0, so whilst a slider is fine for increasing the
// damage,
// it doesn't give fine enough control for values less than 1.
property = config.get(Configuration.CATEGORY_GENERAL, "playerDamageScaling", 1.0,
"Global damage scaling factor for the damage dealt by players casting spells, relative to 1.", 0, 20);
property.setLanguageKey("config." + Wizardry.MODID + ".player_damage_scaling");
playerDamageScale = property.getDouble();
property = config.get(GAMEPLAY_CATEGORY, "summonedCreatureTargetsWhitelist", new String[0],
"List of names of entities which summoned creatures and wizards are allowed to attack, in addition to the defaults. Add mod creatures to this list if you want summoned creatures to attack them and they aren't already doing so. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard).");
property.setLanguageKey("config." + Wizardry.MODID + ".summoned_creature_targets_whitelist");
property.setRequiresWorldRestart(true);
// Converts all strings in the list to a ResourceLocation.
summonedCreatureTargetsWhitelist = Arrays.stream(property.getStringList()).map(s -> new ResourceLocation(s.toLowerCase(Locale.ROOT).trim())).toArray(ResourceLocation[]::new);
propOrder.add(property.getName());
property = config.get(Configuration.CATEGORY_GENERAL, "npcDamageScaling", 1.0,
"Global damage scaling factor for the damage dealt by NPCs casting spells, relative to 1.", 0, 20);
property.setLanguageKey("config." + Wizardry.MODID + ".npc_damage_scaling");
npcDamageScale = property.getDouble();
property = config.get(GAMEPLAY_CATEGORY, "summonedCreatureTargetsBlacklist",
new String[]{"creeper"},
"List of names of entities which summoned creatures and wizards are specifically not allowed to attack, overriding the defaults and the whitelist. Add creatures to this list if allowing them to be attacked causes problems or is too destructive (removing creepers from this list is done at your own risk!). Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard).");
property.setLanguageKey("config." + Wizardry.MODID + ".summoned_creature_targets_blacklist");
property.setRequiresWorldRestart(true);
// Converts all strings in the list to a ResourceLocation.
summonedCreatureTargetsBlacklist = Arrays.stream(property.getStringList()).map(s -> new ResourceLocation(s.toLowerCase(Locale.ROOT).trim())).toArray(ResourceLocation[]::new);
propOrder.add(property.getName());
property = config.get(GAMEPLAY_CATEGORY, "telekineticDisarmament", true,
"Whether to allow players to disarm other players using the telekinesis spell. Set to false to prevent stealing of items.");
property.setLanguageKey("config." + Wizardry.MODID + ".telekinetic_disarmament");
telekineticDisarmament = property.getBoolean();
propOrder.add(property.getName());
property = config.get(GAMEPLAY_CATEGORY, "teleportThroughUnbreakableBlocks", false,
"Whether players are allowed to teleport through unbreakable blocks (e.g. bedrock) using the phase step spell.");
property.setLanguageKey("config." + Wizardry.MODID + ".teleport_through_unbreakable_blocks");
teleportThroughUnbreakableBlocks = property.getBoolean();
propOrder.add(property.getName());
property = config.get(GAMEPLAY_CATEGORY, "mindControlTargetsBlacklist", new String[]{},
"List of names of entities which cannot be mind controlled, in addition to the defaults. Add creatures to this list if allowing them to be mind-controlled causes problems or could be exploited. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard).");
property.setLanguageKey("config." + Wizardry.MODID + ".mind_control_targets_blacklist");
property.setRequiresWorldRestart(true);
// Converts all strings in the list to a ResourceLocation.
mindControlTargetsBlacklist = Arrays.stream(property.getStringList()).map(s -> new ResourceLocation(s.toLowerCase(Locale.ROOT).trim())).toArray(ResourceLocation[]::new);
propOrder.add(property.getName());
config.setCategoryPropertyOrder(GAMEPLAY_CATEGORY, propOrder);
}
private void setupWorldgenConfig(){
// This trick is borrowed from forge; it sorts the config options into the order you want them.
List<String> propOrder = new ArrayList<String>();
Property property;
config.addCustomCategoryComment(WORLDGEN_CATEGORY, "Settings that affect world generation. In multiplayer, the server/LAN host settings will apply.");
property = config.get(WORLDGEN_CATEGORY, "towerRarity", 8, "Rarity of wizard towers. Higher numbers are rarer. Set to 0 to disable wizard towers completely.", 0, 50);
property.setLanguageKey("config." + Wizardry.MODID + ".tower_rarity");
property.setRequiresWorldRestart(true);
Wizardry.proxy.setToNumberSliderEntry(property);
towerRarity = property.getInt();
propOrder.add(property.getName());
property = config.get(WORLDGEN_CATEGORY, "towerDimensions", new int[]{0}, "List of dimension ids in which wizard towers will generate.");
property.setLanguageKey("config." + Wizardry.MODID + ".tower_dimensions");
property.setRequiresWorldRestart(true);
towerDimensions = property.getIntList();
propOrder.add(property.getName());
property = config.get(WORLDGEN_CATEGORY, "oreDimensions", new int[]{0}, "List of dimension ids in which crystal ore will generate. Note that removing the overworld (id 0) from this list will make the mod VERY difficult to play!");
property.setLanguageKey("config." + Wizardry.MODID + ".ore_dimensions");
property.setRequiresWorldRestart(true);
oreDimensions = property.getIntList();
propOrder.add(property.getName());
property = config.get(WORLDGEN_CATEGORY, "flowerDimensions", new int[]{0}, "List of dimension ids in which crystal flowers will generate.");
property.setLanguageKey("config." + Wizardry.MODID + ".flower_dimensions");
property.setRequiresWorldRestart(true);
flowerDimensions = property.getIntList();
propOrder.add(property.getName());
property = config.get(WORLDGEN_CATEGORY, "generateLoot", true, "Whether to inject wizardry loot (as specified in loot_tables/chests/dungeon_additions.json) into the loot tables for vanilla dungeon chests.");
property.setLanguageKey("config." + Wizardry.MODID + ".generate_loot");
property.setRequiresWorldRestart(true);
generateLoot = property.getBoolean();
propOrder.add(property.getName());
config.setCategoryPropertyOrder(WORLDGEN_CATEGORY, propOrder);
}
private void setupClientConfig(){
// This trick is borrowed from forge; it sorts the config options into the order you want them.
List<String> propOrder = new ArrayList<String>();
Property property;
config.addCustomCategoryComment(CLIENT_CATEGORY, "Client-side settings that only affect the local minecraft game. If this file is on a dedicated server, these settings will have no effect; in multiplayer, each player obeys their own settings.");
property = config.get(CLIENT_CATEGORY, "enableShiftScrolling", true,
"Whether you can switch between spells on a wand by scrolling with the mouse wheel while sneaking. Note that this will only affect you; other players connected to the same server obey their own settings.");
property.setLanguageKey("config." + Wizardry.MODID + ".enable_shift_scrolling");
property.setRequiresWorldRestart(false);
enableShiftScrolling = property.getBoolean();
propOrder.add(property.getName());
property = config.get(CLIENT_CATEGORY, "spellHUDPosition", GuiPosition.BOTTOM_LEFT.name, "The position of the spell HUD.", GuiPosition.names);
property.setLanguageKey("config." + Wizardry.MODID + ".spell_hud_position");
spellHUDPosition = GuiPosition.fromName(property.getString());
propOrder.add(property.getName());
property = config.get(CLIENT_CATEGORY, "showSummonedCreatureNames", true, "Whether to show summoned creatures' names and owners above their heads.");
property.setLanguageKey("config." + Wizardry.MODID + ".show_summoned_creature_names");
showSummonedCreatureNames = property.getBoolean();
propOrder.add(property.getName());
config.setCategoryPropertyOrder(CLIENT_CATEGORY, propOrder);
}
private void setupCommandsConfig(){
// This trick is borrowed from forge; it sorts the config options into the order you want them.
List<String> propOrder = new ArrayList<String>();
Property property;
config.addCustomCategoryComment(COMMANDS_CATEGORY, "Settings for the commands added by Wizardry. In multiplayer, the server/LAN host settings will apply.");
// This one isn't a slider either because people are likely to want exact values ("it must be at most 50.3" is a
// bit strange!).
property = config.get(Configuration.CATEGORY_GENERAL, "castCommandMultiplierLimit", 20.0,
property = config.get(COMMANDS_CATEGORY, "castCommandMultiplierLimit", 20.0,
"Upper limit for the multipliers passed into the /cast command. This is here to stop players from accidentally breaking a world/server. Large blast mutipliers can cause extreme lag - you have been warned!",
1, 255);
property.setLanguageKey("config." + Wizardry.MODID + ".cast_command_multiplier_limit");
maxSpellCommandMultiplier = property.getDouble();
propOrder.add(property.getName());
property = config.get(Configuration.CATEGORY_GENERAL, "summonedCreatureTargetsWhitelist", new String[0],
"List of names of entities which summoned creatures and wizards are allowed to attack, in addition to the defaults. Add mod creatures to this list if you want summoned creatures to attack them and they aren't already doing so. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":Wizard).");
property.setLanguageKey("config." + Wizardry.MODID + ".summoned_creature_targets_whitelist");
property.setRequiresWorldRestart(true);
// Wizardry.proxy.setToEntityNameEntry(property);
summonedCreatureTargetsWhitelist = property.getStringList();
// Converts all strings in the list to lower case, to ignore case sensitivity, and trims them.
for(int i = 0; i < summonedCreatureTargetsWhitelist.length; i++){
summonedCreatureTargetsWhitelist[i] = summonedCreatureTargetsWhitelist[i].toLowerCase(Locale.ROOT).trim();
}
propOrder.add(property.getName());
property = config.get(Configuration.CATEGORY_GENERAL, "summonedCreatureTargetsBlacklist",
new String[]{"creeper"},
"List of names of entities which summoned creatures and wizards are specifically not allowed to attack, overriding the defaults and the whitelist. Add creatures to this list if allowing them to be attacked causes problems or is too destructive (removing creepers from this list is done at your own risk!). Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":Wizard).");
property.setLanguageKey("config." + Wizardry.MODID + ".summoned_creature_targets_blacklist");
property.setRequiresWorldRestart(true);
// Wizardry.proxy.setToEntityNameEntry(property);
summonedCreatureTargetsBlacklist = property.getStringList();
// Converts all strings in the list to lower case, to ignore case sensitivity, and trims them.
for(int i = 0; i < summonedCreatureTargetsBlacklist.length; i++){
summonedCreatureTargetsBlacklist[i] = summonedCreatureTargetsBlacklist[i].toLowerCase(Locale.ROOT).trim();
}
propOrder.add(property.getName());
property = config.get(Configuration.CATEGORY_GENERAL, "spellHUDPosition", GuiPosition.BOTTOM_LEFT.name,
"The position of the spell HUD.", GuiPosition.names);
property.setLanguageKey("config." + Wizardry.MODID + ".spell_hud_position");
spellHUDPosition = GuiPosition.fromName(property.getString());
propOrder.add(property.getName());
property = config.get(Configuration.CATEGORY_GENERAL, "castCommandName", "cast",
property = config.get(COMMANDS_CATEGORY, "castCommandName", "cast",
"The name of the /cast command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /cast you would type /magic instead.");
property.setLanguageKey("config." + Wizardry.MODID + ".cast_command_name");
property.setRequiresWorldRestart(true);
castCommandName = property.getString();
propOrder.add(property.getName());
property = config.get(Configuration.CATEGORY_GENERAL, "discoverspellCommandName", "discoverspell",
property = config.get(COMMANDS_CATEGORY, "discoverspellCommandName", "discoverspell",
"The name of the /discoverspell command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /discoverspell you would type /magic instead.");
property.setLanguageKey("config." + Wizardry.MODID + ".discoverspell_command_name");
property.setRequiresWorldRestart(true);
discoverspellCommandName = property.getString();
propOrder.add(property.getName());
property = config.get(Configuration.CATEGORY_GENERAL, "allyCommandName", "ally",
property = config.get(COMMANDS_CATEGORY, "allyCommandName", "ally",
"The name of the /ally command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /ally you would type /magic instead.");
property.setLanguageKey("config." + Wizardry.MODID + ".ally_command_name");
property.setRequiresWorldRestart(true);
allyCommandName = property.getString();
propOrder.add(property.getName());
property = config.get(Configuration.CATEGORY_GENERAL, "alliesCommandName", "allies",
property = config.get(COMMANDS_CATEGORY, "alliesCommandName", "allies",
"The name of the /allies command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /allies you would type /magic instead.");
property.setLanguageKey("config." + Wizardry.MODID + ".allies_command_name");
property.setRequiresWorldRestart(true);
alliesCommandName = property.getString();
propOrder.add(property.getName());
config.setCategoryPropertyOrder(COMMANDS_CATEGORY, propOrder);
}
config.setCategoryPropertyOrder(Configuration.CATEGORY_GENERAL, propOrder);
private void setupResistancesConfig(){
// Resistances
Property property;
List<String> propOrder1 = new ArrayList<String>();
List<String> propOrder = new ArrayList<String>();
config.addCustomCategoryComment(RESISTANCES_CATEGORY,
"Settings which allow entities to be made immune to certain types of magic. In multiplayer, the server/LAN host settings will apply.");
property = config.get(RESISTANCES_CATEGORY, "mobsImmuneToFire", new String[]{},
"List of names of entities that are immune to fire, in addition to the defaults. Add mod creatures to this list if you want them to be immune to fire magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":Wizard).");
"List of names of entities that are immune to fire, in addition to the defaults. Add mod creatures to this list if you want them to be immune to fire magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard).");
property.setLanguageKey("config." + Wizardry.MODID + ".mobs_immune_to_fire");
property.setRequiresMcRestart(true);
// Wizardry.proxy.setToEntityNameEntry(property);
@@ -517,10 +531,10 @@ public final class Settings {
MagicDamage.addEntityImmunity(EntityList.getClass(new ResourceLocation(property.getStringList()[i])),
DamageType.FIRE);
}
propOrder1.add(property.getName());
propOrder.add(property.getName());
property = config.get(RESISTANCES_CATEGORY, "mobsImmuneToIce", new String[]{},
"List of names of entities that are immune to ice, in addition to the defaults. Add mod creatures to this list if you want them to be immune to ice magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":Wizard).");
"List of names of entities that are immune to ice, in addition to the defaults. Add mod creatures to this list if you want them to be immune to ice magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard).");
property.setLanguageKey("config." + Wizardry.MODID + ".mobs_immune_to_ice");
property.setRequiresMcRestart(true);
// Wizardry.proxy.setToEntityNameEntry(property);
@@ -530,10 +544,10 @@ public final class Settings {
MagicDamage.addEntityImmunity(EntityList.getClass(new ResourceLocation(property.getStringList()[i])),
DamageType.FROST);
}
propOrder1.add(property.getName());
propOrder.add(property.getName());
property = config.get(RESISTANCES_CATEGORY, "mobsImmuneToLightning", new String[]{},
"List of names of entities that are immune to lightning, in addition to the defaults. Add mod creatures to this list if you want them to be immune to lightning magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":Wizard).");
"List of names of entities that are immune to lightning, in addition to the defaults. Add mod creatures to this list if you want them to be immune to lightning magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard).");
property.setLanguageKey("config." + Wizardry.MODID + ".mobs_immune_to_lightning");
property.setRequiresMcRestart(true);
// Wizardry.proxy.setToEntityNameEntry(property);
@@ -543,10 +557,10 @@ public final class Settings {
MagicDamage.addEntityImmunity(EntityList.getClass(new ResourceLocation(property.getStringList()[i])),
DamageType.SHOCK);
}
propOrder1.add(property.getName());
propOrder.add(property.getName());
property = config.get(RESISTANCES_CATEGORY, "mobsImmuneToWither", new String[]{},
"List of names of entities that are immune to wither effects, in addition to the defaults. Add mod creatures to this list if you want them to be immune to withering magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":Wizard).");
"List of names of entities that are immune to wither effects, in addition to the defaults. Add mod creatures to this list if you want them to be immune to withering magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard).");
property.setLanguageKey("config." + Wizardry.MODID + ".mobs_immune_to_wither");
property.setRequiresMcRestart(true);
// Wizardry.proxy.setToEntityNameEntry(property);
@@ -556,10 +570,10 @@ public final class Settings {
MagicDamage.addEntityImmunity(EntityList.getClass(new ResourceLocation(property.getStringList()[i])),
DamageType.WITHER);
}
propOrder1.add(property.getName());
propOrder.add(property.getName());
property = config.get(RESISTANCES_CATEGORY, "mobsImmuneToPoison", new String[]{},
"List of names of entities that are immune to poison, in addition to the defaults. Add mod creatures to this list if you want them to be immune to poison magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":Wizard).");
"List of names of entities that are immune to poison, in addition to the defaults. Add mod creatures to this list if you want them to be immune to poison magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard).");
property.setLanguageKey("config." + Wizardry.MODID + ".mobs_immune_to_poison");
property.setRequiresMcRestart(true);
// Wizardry.proxy.setToEntityNameEntry(property);
@@ -569,19 +583,9 @@ public final class Settings {
MagicDamage.addEntityImmunity(EntityList.getClass(new ResourceLocation(property.getStringList()[i])),
DamageType.POISON);
}
propOrder1.add(property.getName());
config.setCategoryPropertyOrder(RESISTANCES_CATEGORY, propOrder1);
// config.addCustomCategoryComment(CLIENT_CATEGORY, "Client-side settings that only affect the local minecraft
// game. They have no effect on a server; each player obeys their own settings.");
// config.addCustomCategoryComment(COMMANDS_CATEGORY, "Settings for the commands added by Wizardry. In
// multiplayer, the server/LAN host settings will apply.");
// config.addCustomCategoryComment(WORLDGEN_CATEGORY, "Settings that affect world generation. In multiplayer,
// the server/LAN host settings will apply.");
// config.addCustomCategoryComment(GLOBAL_CATEGORY, "Global settings that affect game mechanics. In multiplayer,
// the server/LAN host settings will apply.");
propOrder.add(property.getName());
config.setCategoryPropertyOrder(RESISTANCES_CATEGORY, propOrder);
}
}
@@ -33,12 +33,12 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Items;
import net.minecraft.init.MobEffects;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.ItemEnchantedBook;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagInt;
import net.minecraft.nbt.NBTTagString;
import net.minecraft.nbt.*;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
@@ -278,12 +278,14 @@ public class WizardData implements INBTSerializable<NBTTagCompound> {
for(ItemStack stack : player.inventory.mainInventory){
if(stack.isItemEnchanted()){
Map<Enchantment, Integer> enchantments = EnchantmentHelper.getEnchantments(stack);
NBTTagList enchantmentList = stack.getItem() == Items.ENCHANTED_BOOK ?
ItemEnchantedBook.getEnchantments(stack) : stack.getEnchantmentTagList();
Iterator<Entry<Enchantment, Integer>> iterator = enchantments.entrySet().iterator();
Iterator<NBTBase> iterator =enchantmentList.iterator();
// For each of the item's enchantments
while(iterator.hasNext()){
Enchantment enchantment = iterator.next().getKey();
NBTTagCompound enchantmentTag = (NBTTagCompound) iterator.next();
Enchantment enchantment = Enchantment.getEnchantmentByID(enchantmentTag.getShort("id"));
// Ignores the enchantment unless it is an imbuement
if(enchantment instanceof Imbuement){
int duration = this.getImbuementDuration(enchantment);
@@ -295,10 +297,8 @@ public class WizardData implements INBTSerializable<NBTTagCompound> {
activeImbuements.add((Imbuement)enchantment);
// Otherwise:
}else{
// Removes the enchantment from the enchantment map
// Removes the enchantment from the item
iterator.remove();
// Applies the new enchantment map to the item
EnchantmentHelper.setEnchantments(enchantments, stack);
}
}
}
@@ -48,7 +48,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.1.1";
public static final String VERSION = "4.1.3";
// IDEA: Improve the algorithm that finds a place to summon creatures to take walls into account.
// IDEA: Replace all uses of Math.cos and Math.sin with MathHelper versions
@@ -66,19 +66,6 @@ public class Wizardry {
// I can make the healing spells use damage multipliers - hurrah!
// TODO: Switch from IInventory to IItemHandler (Or don't. It's only useful for automation really.)
// TODO: Rearrange the config gui and file
// Updating:
// TODO: Make sure all obf reflection names are still correct
// TODO: Go through each of the summoned creatures and check there are no extra vanilla methods to override
// TODO: Check whether Minecraft has added some methods that do the same job as my utilities, particularly in
// relation to itemstacks, hotbar, armour slots and inventory slots.
// TODO: Add wizard towers to the /locate command
// TODO: Fix cascading worldgen lag and backport (offset area into loaded chunks, possibly use WorldGenMinable)
// TODO: Change evil wizard sounds again to use illager sounds?
// TODO: Chnage all instanceof checks on split entity variant classes (zombie, skeleton, etc.) to their abstract
// base classes where appropriate
// TODO: Have particles obey Minecraft's particle setting where appropriate
// (see https://github.com/RootsTeam/Embers/blob/master/src/main/java/teamroots/embers/particle/ParticleUtil.java)
@@ -188,15 +175,15 @@ public class Wizardry {
// 2.1 changed some item ids, so this fixes them for existing worlds
// Nobody updates minecraft versions when using mods, but I may as well leave this here just in case.
@EventHandler
@SubscribeEvent
public static void onMissingMappingEvent(RegistryEvent.MissingMappings<Item> event){
// Just get, not getAll, since the mod id didn't change!
for(RegistryEvent.MissingMappings.Mapping<Item> mapping : event.getAllMappings()){
if(mapping.key.getResourceDomain().equals(Wizardry.MODID)){
if(mapping.key.getNamespace().equals(Wizardry.MODID)){
Item replacement = null;
switch(mapping.key.getResourcePath()){
switch(mapping.key.getPath()){
case "wand_basic": replacement = WizardryItems.magic_wand; break;
case "wand_basic_fire": replacement = WizardryItems.basic_fire_wand; break;
@@ -50,6 +50,7 @@ import net.minecraft.world.storage.loot.LootPool;
import net.minecraft.world.storage.loot.RandomValueRange;
import net.minecraft.world.storage.loot.conditions.LootCondition;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.event.LootTableLoadEvent;
import net.minecraftforge.event.entity.living.LivingAttackEvent;
import net.minecraftforge.event.entity.living.LivingDeathEvent;
@@ -199,7 +200,8 @@ public final class WizardryEventHandler {
// Ice Shroud
if(event.getEntityLiving().isPotionActive(WizardryPotions.ice_shroud)
&& !MagicDamage.isEntityImmune(DamageType.FROST, event.getEntityLiving()))
&& !MagicDamage.isEntityImmune(DamageType.FROST, event.getEntityLiving())
&& !(event.getEntityLiving() instanceof FakePlayer))
attacker.addPotionEffect(new PotionEffect(WizardryPotions.frost, 100, 0));
// Static Aura
@@ -1,67 +1,64 @@
package electroblob.wizardry;
import org.lwjgl.input.Keyboard;
import electroblob.wizardry.client.ClientProxy;
import electroblob.wizardry.item.ItemWand;
import electroblob.wizardry.packet.PacketControlInput;
import electroblob.wizardry.packet.WizardryPacketHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.InputEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
public class WizardryKeyHandler {
boolean NkeyPressed = false;
boolean BkeyPressed = false;
boolean NkeyAlreadyPressed = false;
boolean BkeyAlreadyPressed = false;
// Changed to a tick event to allow mouse button keybinds
// The 'lag' that happened previously was actually because the code only fired when a keyboard key was pressed!
@SubscribeEvent
public void onKeyInput(InputEvent.KeyInputEvent event){
public void onTickEvent(TickEvent.ClientTickEvent event){
// Key pressed
if(Keyboard.getEventKeyState()){
if(event.phase == TickEvent.Phase.END) return; // Only really needs to be once per tick
if(Wizardry.proxy instanceof ClientProxy){
if(Wizardry.proxy instanceof ClientProxy){
if(ClientProxy.NEXT_SPELL.isPressed() && Minecraft.getMinecraft().inGameHasFocus){
if(!NkeyPressed){
NkeyPressed = true;
}else{
NkeyAlreadyPressed = true;
}
if(!NkeyAlreadyPressed){
// Packet building
IMessage msg = new PacketControlInput.Message(PacketControlInput.ControlType.NEXT_SPELL_KEY);
WizardryPacketHandler.net.sendToServer(msg);
}
}
EntityPlayer player = Minecraft.getMinecraft().player;
if(ClientProxy.PREVIOUS_SPELL.isPressed() && Minecraft.getMinecraft().inGameHasFocus){
if(!BkeyPressed){
BkeyPressed = true;
}else{
BkeyAlreadyPressed = true;
}
if(!BkeyAlreadyPressed){
// Packet building
IMessage msg = new PacketControlInput.Message(
PacketControlInput.ControlType.PREVIOUS_SPELL_KEY);
WizardryPacketHandler.net.sendToServer(msg);
}
if(player != null){
ItemStack wand = player.getHeldItemMainhand();
if(!(wand.getItem() instanceof ItemWand)){
wand = player.getHeldItemOffhand();
// If the player isn't holding a wand, then nothing else needs to be done.
if(!(wand.getItem() instanceof ItemWand)) return;
}
}
}
// Key released
else{
if(NkeyPressed){
if(ClientProxy.NEXT_SPELL.isKeyDown() && Minecraft.getMinecraft().inGameHasFocus){
if(!NkeyPressed){
NkeyPressed = true;
// Packet building
IMessage msg = new PacketControlInput.Message(PacketControlInput.ControlType.NEXT_SPELL_KEY);
WizardryPacketHandler.net.sendToServer(msg);
}
}else{
NkeyPressed = false;
NkeyAlreadyPressed = false;
}else if(BkeyPressed){
}
if(ClientProxy.PREVIOUS_SPELL.isKeyDown() && Minecraft.getMinecraft().inGameHasFocus){
if(!BkeyPressed){
BkeyPressed = true;
// Packet building
IMessage msg = new PacketControlInput.Message(
PacketControlInput.ControlType.PREVIOUS_SPELL_KEY);
WizardryPacketHandler.net.sendToServer(msg);
}
}else{
BkeyPressed = false;
BkeyAlreadyPressed = false;
}
}
}
@@ -175,7 +175,7 @@ public class WizardryWorldGenerator implements IWorldGenerator {
}
// 0 = West, 1 = North, 2 = East, 3 = South (The way you would face when walking out of the door)
EnumFacing orientation = EnumFacing.getHorizontal(random.nextInt(4));
EnumFacing orientation = EnumFacing.byHorizontalIndex(random.nextInt(4));
boolean flip = random.nextBoolean();
if(checkSpaceForTower(world, origin, towerBlueprint, orientation, flip)){
@@ -237,7 +237,8 @@ public class WizardryWorldGenerator implements IWorldGenerator {
// BlockPos is immutable, so I'm not sure if simply saying pos1 = pos will be sufficient.
BlockPos layerCentre = new BlockPos(origin);
while(flag){
// Stop when the bottom of the world is reached
while(flag && layerCentre.getY() > 0){
flag = false;
@@ -299,7 +300,7 @@ public class WizardryWorldGenerator implements IWorldGenerator {
// Rotates the door depending on whether flip is true.
ItemDoor.placeDoor(
world, pos, flip
? EnumFacing.getHorizontal(3 - orientation.getHorizontalIndex())
? EnumFacing.byHorizontalIndex(3 - orientation.getHorizontalIndex())
.getOpposite()
: orientation.rotateYCCW(),
Blocks.OAK_DOOR, false);
@@ -1,17 +1,13 @@
package electroblob.wizardry.block;
import java.util.Random;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.WizardryGuiHandler;
import electroblob.wizardry.tileentity.TileEntityArcaneWorkbench;
import net.minecraft.block.BlockContainer;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.inventory.InventoryHelper;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumBlockRenderType;
import net.minecraft.util.EnumFacing;
@@ -65,59 +61,20 @@ public class BlockArcaneWorkbench extends BlockContainer {
return false;
}
player.openGui(Wizardry.instance, WizardryGuiHandler.ARCANE_WORKBENCH, world, pos.getX(), pos.getY(),
pos.getZ());
player.openGui(Wizardry.instance, WizardryGuiHandler.ARCANE_WORKBENCH, world, pos.getX(), pos.getY(), pos.getZ());
return true;
}
@Override
public void breakBlock(World world, BlockPos pos, IBlockState block){
TileEntity tileentity = world.getTileEntity(pos);
Random random = new Random();
TileEntityArcaneWorkbench tileentityarcaneworkbench = (TileEntityArcaneWorkbench)world.getTileEntity(pos);
if(tileentity instanceof TileEntityArcaneWorkbench){
InventoryHelper.dropInventoryItems(world, pos, (TileEntityArcaneWorkbench)tileentity);
}
if(tileentityarcaneworkbench != null){
for(int j1 = 0; j1 < tileentityarcaneworkbench.getSizeInventory(); ++j1){
ItemStack itemstack = tileentityarcaneworkbench.getStackInSlot(j1);
if(!itemstack.isEmpty()){
float f = random.nextFloat() * 0.8F + 0.1F;
float f1 = random.nextFloat() * 0.8F + 0.1F;
EntityItem entityitem;
for(float f2 = random.nextFloat() * 0.8F + 0.1F; itemstack.getCount() > 0; world
.spawnEntity(entityitem)){
int k1 = random.nextInt(21) + 10;
if(k1 > itemstack.getCount()){
k1 = itemstack.getCount();
}
itemstack.shrink(k1);
entityitem = new EntityItem(world, (double)((float)pos.getX() + f),
(double)((float)pos.getY() + f1), (double)((float)pos.getZ() + f2),
new ItemStack(itemstack.getItem(), k1, itemstack.getItemDamage()));
float f3 = 0.05F;
entityitem.motionX = (double)((float)random.nextGaussian() * f3);
entityitem.motionY = (double)((float)random.nextGaussian() * f3 + 0.2F);
entityitem.motionZ = (double)((float)random.nextGaussian() * f3);
if(itemstack.hasTagCompound()){
entityitem.getItem().setTagCompound(((NBTTagCompound)itemstack.getTagCompound().copy()));
}
}
}
}
// par1World.func_96440_m(par2, par3, par4, block);
}
super.breakBlock(world, pos, block);
super.breakBlock(world, pos, block);
}
}
@@ -8,6 +8,10 @@ import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.item.Item;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
public class BlockCrystalOre extends Block {
@@ -20,10 +24,17 @@ public class BlockCrystalOre extends Block {
@Override
public int quantityDropped(IBlockState state, int fortune, Random random){
// This now works the same way as vanilla ores
if(fortune > 0){
return random.nextInt(2) + 1 + random.nextInt(fortune);
int i = random.nextInt(fortune + 2) - 1;
if(i < 0) i = 0;
return (random.nextInt(3) + 1) * (i + 1);
}else{
return random.nextInt(2) + 1;
return random.nextInt(3) + 1;
}
}
@@ -31,4 +42,16 @@ public class BlockCrystalOre extends Block {
public Item getItemDropped(IBlockState state, Random random, int fortune){
return WizardryItems.magic_crystal;
}
@Override
public int getExpDrop(IBlockState state, IBlockAccess world, BlockPos pos, int fortune){
Random rand = world instanceof World ? ((World)world).rand : RANDOM;
if(this.getItemDropped(state, rand, fortune) != Item.getItemFromBlock(this)){
return MathHelper.getInt(rand, 1, 4);
}
return 0;
}
}
@@ -51,7 +51,7 @@ public class BlockSnare extends BlockContainer {
}
@Override
public void onEntityCollidedWithBlock(World world, BlockPos pos, IBlockState state, Entity entity){
public void onEntityCollision(World world, BlockPos pos, IBlockState state, Entity entity){
if(!world.isRemote && entity instanceof EntityLivingBase){
if(world.getTileEntity(pos) instanceof TileEntityPlayerSave){
@@ -80,7 +80,7 @@ public class BlockSnare extends BlockContainer {
}
@Override
public BlockRenderLayer getBlockLayer(){
public BlockRenderLayer getRenderLayer() {
return BlockRenderLayer.CUTOUT;
}
@@ -36,7 +36,7 @@ public class BlockSpectral extends BlockContainer {
// Replaces getRenderBlockPass
@Override
public BlockRenderLayer getBlockLayer(){
public BlockRenderLayer getRenderLayer(){
return BlockRenderLayer.TRANSLUCENT;
}
@@ -97,7 +97,7 @@ public class BlockStatue extends BlockContainer {
}
@Override
public BlockRenderLayer getBlockLayer(){
public BlockRenderLayer getRenderLayer(){
return this.isIce ? BlockRenderLayer.TRANSLUCENT : BlockRenderLayer.SOLID;
}
@@ -66,14 +66,15 @@ public class BlockTransportationStone extends Block {
return false;
}
@SuppressWarnings("deprecation")
@Override
public void onNeighborChange(IBlockAccess world, BlockPos pos, BlockPos neighbor){
public void neighborChanged(IBlockState state, World world, BlockPos pos, Block block, BlockPos fromPos){
super.onNeighborChange(world, pos, neighbor);
super.neighborChanged(state, world, pos, block, fromPos);
if(!world.isSideSolid(pos.down(), EnumFacing.UP, false) && world instanceof World){
this.dropBlockAsItem((World)world, pos, world.getBlockState(pos), 0);
((World)world).setBlockToAir(pos);
if(!world.isSideSolid(pos.down(), EnumFacing.UP, false)){
this.dropBlockAsItem(world, pos, world.getBlockState(pos), 0);
world.setBlockToAir(pos);
}
}
@@ -55,7 +55,7 @@ public class BlockVanishingCobweb extends BlockContainer {
}
@Override
public void onEntityCollidedWithBlock(World world, BlockPos pos, IBlockState state, Entity entity){
public void onEntityCollision(World world, BlockPos pos, IBlockState state, Entity entity){
entity.setInWeb();
}
@@ -53,6 +53,8 @@ public class GuiArcaneWorkbench extends GuiContainer {
@Override
public void drawScreen(int p_73863_1_, int p_73863_2_, float p_73863_3_){
this.drawDefaultBackground();
// Tests if there is a wand in the workbench and edits the positioning accordingly
if(this.inventorySlots.getSlot(ContainerArcaneWorkbench.WAND_SLOT).getHasStack() && this.inventorySlots
.getSlot(ContainerArcaneWorkbench.WAND_SLOT).getStack().getItem() instanceof ItemWand){
@@ -80,8 +82,6 @@ public class GuiArcaneWorkbench extends GuiContainer {
@Override
public void drawGuiContainerBackgroundLayer(float f, int mouseX, int mouseY){
GlStateManager.pushAttrib();
GlStateManager.color(1F, 1F, 1F, 1F);
Minecraft.getMinecraft().renderEngine.bindTexture(texture);
@@ -152,8 +152,6 @@ public class GuiArcaneWorkbench extends GuiContainer {
// Fixes the bug that caused the slot hightlight to render opaque. I don't know why it works, it just works!
GlStateManager.disableBlend();
GlStateManager.enableAlpha();
GlStateManager.popAttrib();
}
@Override
@@ -24,57 +24,107 @@ public class GuiConfigWizardry extends GuiConfig {
}
private static List<IConfigElement> getConfigEntries(){
List<IConfigElement> configList = new ArrayList<IConfigElement>(1);
configList.add(new DummyCategoryElement("spellsConfig", "config." + Wizardry.MODID + ".category." + Settings.SPELLS_CATEGORY,
SpellsCategory.class));
configList.add(new DummyCategoryElement("resistancesConfig",
"config." + Wizardry.MODID + ".category." + Settings.RESISTANCES_CATEGORY, ResistancesCategory.class));
configList.addAll(new ConfigElement(Wizardry.settings.getConfigCategory(Configuration.CATEGORY_GENERAL))
.getChildElements());
configList.add(new DummyCategoryElement("gameplayConfig", "config." + Wizardry.MODID + ".category." + Settings.GAMEPLAY_CATEGORY, GameplayCategory.class));
configList.add(new DummyCategoryElement("worldgenConfig", "config." + Wizardry.MODID + ".category." + Settings.WORLDGEN_CATEGORY, WorldgenCategory.class));
configList.add(new DummyCategoryElement("commandsConfig", "config." + Wizardry.MODID + ".category." + Settings.COMMANDS_CATEGORY, CommandsCategory.class));
configList.add(new DummyCategoryElement("clientConfig", "config." + Wizardry.MODID + ".category." + Settings.CLIENT_CATEGORY, ClientCategory.class));
configList.add(new DummyCategoryElement("spellsConfig", "config." + Wizardry.MODID + ".category." + Settings.SPELLS_CATEGORY, SpellsCategory.class));
configList.add(new DummyCategoryElement("resistancesConfig", "config." + Wizardry.MODID + ".category." + Settings.RESISTANCES_CATEGORY, ResistancesCategory.class));
configList.addAll(new ConfigElement(Wizardry.settings.getConfigCategory(Configuration.CATEGORY_GENERAL)).getChildElements());
return configList;
}
// The reason this system is so convoluted is that it's designed for use with the @Config annotation. The problem is,
// I'm not sure whether that will play well with the load phases. Hmmm...
public static abstract class CategoryBase extends CategoryEntry {
public CategoryBase(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){
super(owningScreen, owningEntryList, prop);
}
/** Spells category of the config gui. This adds a button which opens up the spells category config. */
public static class SpellsCategory extends CategoryEntry {
@Override
protected GuiScreen buildChildScreen(){
String category = this.getCategory();
// This GuiConfig object specifies the configID of the object and as such will force-save when it is closed.
// The parent GuiConfig object's entryList will also be refreshed to reflect the changes.
GuiConfig childScreen = new GuiConfig(this.owningScreen,
(new ConfigElement(Wizardry.settings.getConfigCategory(category))).getChildElements(),
this.owningScreen.modID, category, false, false,
Wizardry.NAME + " - " + I18n.format("config." + Wizardry.MODID + ".title." + category));
childScreen.titleLine2 = I18n.format("config." + Wizardry.MODID + ".subtitle." + category);
return childScreen;
}
protected abstract String getCategory();
}
/** Gameplay category of the config gui. */
public static class GameplayCategory extends CategoryBase {
public GameplayCategory(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){
super(owningScreen, owningEntryList, prop);
}
@Override protected String getCategory() { return Settings.GAMEPLAY_CATEGORY; }
}
/** Spells category of the config gui. */
public static class SpellsCategory extends CategoryBase {
public SpellsCategory(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){
super(owningScreen, owningEntryList, prop);
}
@Override
protected GuiScreen buildChildScreen(){
// This GuiConfig object specifies the configID of the object and as such will force-save when it is closed.
// The parent GuiConfig object's entryList will also be refreshed to reflect the changes.
GuiConfig spellsMenu = new GuiConfig(this.owningScreen,
(new ConfigElement(Wizardry.settings.getConfigCategory(Settings.SPELLS_CATEGORY)))
.getChildElements(),
this.owningScreen.modID, Settings.SPELLS_CATEGORY, false, false,
Wizardry.NAME + " - " + I18n.format("config." + Wizardry.MODID + ".title." + Settings.SPELLS_CATEGORY));
spellsMenu.titleLine2 = I18n.format("config." + Wizardry.MODID + ".subtitle." + Settings.SPELLS_CATEGORY);
return spellsMenu;
}
@Override protected String getCategory() { return Settings.SPELLS_CATEGORY; }
}
/** Resistances category of the config gui. */
public static class ResistancesCategory extends CategoryEntry {
public static class ResistancesCategory extends CategoryBase {
public ResistancesCategory(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){
super(owningScreen, owningEntryList, prop);
}
@Override
protected GuiScreen buildChildScreen(){
// This GuiConfig object specifies the configID of the object and as such will force-save when it is closed.
// The parent GuiConfig object's entryList will also be refreshed to reflect the changes.
GuiConfig idsMenu = new GuiConfig(this.owningScreen,
(new ConfigElement(Wizardry.settings.getConfigCategory(Settings.RESISTANCES_CATEGORY)))
.getChildElements(),
this.owningScreen.modID, Settings.RESISTANCES_CATEGORY, false, false,
Wizardry.NAME + " - " + I18n.format("config." + Wizardry.MODID + ".title." + Settings.RESISTANCES_CATEGORY));
idsMenu.titleLine2 = I18n.format("config." + Wizardry.MODID + ".subtitle." + Settings.RESISTANCES_CATEGORY);
return idsMenu;
@Override protected String getCategory() { return Settings.RESISTANCES_CATEGORY; }
}
/** Worldgen category of the config gui. */
public static class WorldgenCategory extends CategoryBase {
public WorldgenCategory(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){
super(owningScreen, owningEntryList, prop);
}
@Override protected String getCategory() { return Settings.WORLDGEN_CATEGORY; }
}
/** Client category of the config gui. */
public static class ClientCategory extends CategoryBase {
public ClientCategory(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){
super(owningScreen, owningEntryList, prop);
}
@Override protected String getCategory() { return Settings.CLIENT_CATEGORY; }
}
/** Commands category of the config gui. */
public static class CommandsCategory extends CategoryBase {
public CommandsCategory(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){
super(owningScreen, owningEntryList, prop);
}
@Override protected String getCategory() { return Settings.COMMANDS_CATEGORY; }
}
}
@@ -122,8 +122,6 @@ public class GuiSpellDisplay extends Gui {
}else if(event.getType() == RenderGameOverlayEvent.ElementType.HOTBAR){
GlStateManager.pushAttrib();
GlStateManager.enableBlend();
GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA);
GlStateManager.color(1, 1, 1);
@@ -146,8 +144,8 @@ public class GuiSpellDisplay extends Gui {
this.mc.renderEngine.bindTexture(discovered ? spell.getIcon() : Spells.none.getIcon());
WizardryUtilities.drawTexturedRect(mirror ? left + 94 : left + 2, top + 2, 0, 0, 32, 32, 32, 32);
GlStateManager.popAttrib();
// Blend needs to be left enabled here because otherwise the hotbar becomes opaque
}
}
@@ -182,7 +182,7 @@ public class GuiWizardHandbook extends GuiScreen {
RenderHelper.enableGUIStandardItemLighting();
GlStateManager.disableLighting();
GlStateManager.enableRescaleNormal();
GL11.glEnable(GL11.GL_COLOR_MATERIAL);
GlStateManager.enableColorMaterial();
GlStateManager.enableLighting();
itemRender.zLevel = 100.0F;
@@ -204,7 +204,7 @@ public class GuiWizardHandbook extends GuiScreen {
GlStateManager.popMatrix();
GlStateManager.enableLighting();
GL11.glEnable(GL11.GL_DEPTH_TEST);
GlStateManager.enableDepth();
RenderHelper.enableStandardItemLighting();
}
@@ -219,7 +219,7 @@ public class GuiWizardHandbook extends GuiScreen {
RenderHelper.enableGUIStandardItemLighting();
GlStateManager.disableLighting();
GlStateManager.enableRescaleNormal();
GL11.glEnable(GL11.GL_COLOR_MATERIAL);
GlStateManager.enableColorMaterial();
itemRender.zLevel = 0.0F;
GlStateManager.disableLighting();
@@ -239,7 +239,7 @@ public class GuiWizardHandbook extends GuiScreen {
GlStateManager.popMatrix();
GlStateManager.enableLighting();
GL11.glEnable(GL11.GL_DEPTH_TEST);
GlStateManager.enableDepth();
RenderHelper.enableStandardItemLighting();
}
@@ -345,8 +345,8 @@ public class GuiWizardHandbook extends GuiScreen {
}else{
paragraph = paragraph.replaceAll("NEXT_SPELL_KEY", Keyboard.getKeyName(ClientProxy.NEXT_SPELL.getKeyCode()));
paragraph = paragraph.replaceAll("PREVIOUS_SPELL_KEY", Keyboard.getKeyName(ClientProxy.PREVIOUS_SPELL.getKeyCode()));
paragraph = paragraph.replaceAll("NEXT_SPELL_KEY", ClientProxy.NEXT_SPELL.getDisplayName());
paragraph = paragraph.replaceAll("PREVIOUS_SPELL_KEY", ClientProxy.PREVIOUS_SPELL.getDisplayName());
paragraph = paragraph.replaceAll("MANA_PER_CRYSTAL_MINUS_30", "" + (Constants.MANA_PER_CRYSTAL - 30));
paragraph = paragraph.replaceAll("MANA_PER_CRYSTAL", "" + Constants.MANA_PER_CRYSTAL);
paragraph = paragraph.replaceAll("BASIC_MAX_CHARGE", "" + Tier.BASIC.maxCharge);
@@ -659,51 +659,36 @@ public class GuiWizardHandbook extends GuiScreen {
craftingGrid.get(2).set(1, new ItemStack(WizardryItems.magic_silk));
craftingResult = new ItemStack(WizardryItems.wizard_boots);
RECIPES.add(ImmutablePair.of(craftingResult, craftingGrid));
if(Wizardry.settings.useAlternateScrollRecipe){
craftingGrid = createGrid();
craftingGrid.get(0).set(0, new ItemStack(Items.PAPER));
craftingGrid.get(1).set(0, new ItemStack(Items.STRING));
craftingGrid.get(2).set(0, new ItemStack(WizardryItems.magic_crystal));
craftingResult = new ItemStack(WizardryItems.blank_scroll);
RECIPES.add(ImmutablePair.of(craftingResult, craftingGrid));
}else{
craftingGrid = createGrid();
craftingGrid.get(0).set(0, new ItemStack(Items.PAPER));
craftingGrid.get(1).set(0, new ItemStack(Items.STRING));
craftingResult = new ItemStack(WizardryItems.blank_scroll);
RECIPES.add(ImmutablePair.of(craftingResult, craftingGrid));
}
if(Wizardry.settings.firebombIsCraftable){
craftingGrid = createGrid();
craftingGrid.get(0).set(0, new ItemStack(Items.BLAZE_POWDER));
craftingGrid.get(1).set(0, new ItemStack(Items.BLAZE_POWDER));
craftingGrid.get(0).set(1, new ItemStack(Items.GLASS_BOTTLE));
craftingGrid.get(1).set(1, new ItemStack(Items.GUNPOWDER));
craftingResult = new ItemStack(WizardryItems.firebomb, 3);
RECIPES.add(ImmutablePair.of(craftingResult, craftingGrid));
}
if(Wizardry.settings.poisonBombIsCraftable){
craftingGrid = createGrid();
craftingGrid.get(0).set(0, new ItemStack(Items.SPIDER_EYE));
craftingGrid.get(1).set(0, new ItemStack(Items.SPIDER_EYE));
craftingGrid.get(0).set(1, new ItemStack(Items.GLASS_BOTTLE));
craftingGrid.get(1).set(1, new ItemStack(Items.GUNPOWDER));
craftingResult = new ItemStack(WizardryItems.poison_bomb, 3);
RECIPES.add(ImmutablePair.of(craftingResult, craftingGrid));
}
if(Wizardry.settings.smokeBombIsCraftable){
craftingGrid = createGrid();
craftingGrid.get(0).set(0, new ItemStack(Items.COAL));
craftingGrid.get(1).set(0, new ItemStack(Items.COAL));
craftingGrid.get(0).set(1, new ItemStack(Items.GLASS_BOTTLE));
craftingGrid.get(1).set(1, new ItemStack(Items.GUNPOWDER));
craftingResult = new ItemStack(WizardryItems.smoke_bomb, 3);
RECIPES.add(ImmutablePair.of(craftingResult, craftingGrid));
}
craftingGrid = createGrid();
craftingGrid.get(0).set(0, new ItemStack(Items.PAPER));
craftingGrid.get(1).set(0, new ItemStack(Items.STRING));
craftingResult = new ItemStack(WizardryItems.blank_scroll);
RECIPES.add(ImmutablePair.of(craftingResult, craftingGrid));
craftingGrid = createGrid();
craftingGrid.get(0).set(0, new ItemStack(Items.BLAZE_POWDER));
craftingGrid.get(1).set(0, new ItemStack(Items.BLAZE_POWDER));
craftingGrid.get(0).set(1, new ItemStack(Items.GLASS_BOTTLE));
craftingGrid.get(1).set(1, new ItemStack(Items.GUNPOWDER));
craftingResult = new ItemStack(WizardryItems.firebomb, 3);
RECIPES.add(ImmutablePair.of(craftingResult, craftingGrid));
craftingGrid = createGrid();
craftingGrid.get(0).set(0, new ItemStack(Items.SPIDER_EYE));
craftingGrid.get(1).set(0, new ItemStack(Items.SPIDER_EYE));
craftingGrid.get(0).set(1, new ItemStack(Items.GLASS_BOTTLE));
craftingGrid.get(1).set(1, new ItemStack(Items.GUNPOWDER));
craftingResult = new ItemStack(WizardryItems.poison_bomb, 3);
RECIPES.add(ImmutablePair.of(craftingResult, craftingGrid));
craftingGrid = createGrid();
craftingGrid.get(0).set(0, new ItemStack(Items.COAL));
craftingGrid.get(1).set(0, new ItemStack(Items.COAL));
craftingGrid.get(0).set(1, new ItemStack(Items.GLASS_BOTTLE));
craftingGrid.get(1).set(1, new ItemStack(Items.GUNPOWDER));
craftingResult = new ItemStack(WizardryItems.smoke_bomb, 3);
RECIPES.add(ImmutablePair.of(craftingResult, craftingGrid));
}
}
@@ -1,7 +1,5 @@
package electroblob.wizardry.client;
import java.lang.reflect.Field;
import org.lwjgl.opengl.GL11;
import electroblob.wizardry.WizardData;
@@ -21,7 +19,6 @@ import electroblob.wizardry.util.WandHelper;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiMerchant;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
@@ -50,7 +47,6 @@ import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.relauncher.ReflectionHelper;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@@ -73,12 +69,6 @@ public final class WizardryClientEventHandler {
private static final ResourceLocation pointerTexture = new ResourceLocation(Wizardry.MODID, "textures/entity/pointer.png");
private static final ResourceLocation targetPointerTexture = new ResourceLocation(Wizardry.MODID, "textures/entity/target_pointer.png");
private static final Field ITEM_RENDERER;
static {
ITEM_RENDERER = ReflectionHelper.findField(GuiScreen.class, "itemRender", "field_146296_j");
}
@SubscribeEvent
public static void onTextureStitchEvent(TextureStitchEvent.Pre event){
event.getMap().registerSprite(ContainerArcaneWorkbench.EMPTY_SLOT_CRYSTAL);
@@ -164,36 +154,30 @@ public final class WizardryClientEventHandler {
}
private static void renderItemAndTooltip(GuiContainer gui, ItemStack stack, int x, int y, int mouseX, int mouseY, boolean tooltip){
try {
RenderItem renderItem = (RenderItem)ITEM_RENDERER.get(gui);
GlStateManager.pushMatrix();
RenderHelper.enableGUIStandardItemLighting();
GlStateManager.disableLighting();
GlStateManager.enableRescaleNormal();
GL11.glEnable(GL11.GL_COLOR_MATERIAL);
GlStateManager.enableLighting();
renderItem.zLevel = 100.0F;
if(!stack.isEmpty()){
renderItem.renderItemAndEffectIntoGUI(stack, x, y);
renderItem.renderItemOverlays(Minecraft.getMinecraft().fontRenderer, stack, x, y);
if(tooltip){
gui.drawHoveringText(gui.getItemToolTip(stack), mouseX + gui.getXSize()/2 - gui.width/2,
mouseY + gui.getYSize()/2 - gui.height/2);
}
}
GlStateManager.popMatrix();
GlStateManager.enableLighting();
GL11.glEnable(GL11.GL_DEPTH_TEST);
RenderHelper.enableStandardItemLighting();
} catch (Exception e){
e.printStackTrace();
RenderItem renderItem = Minecraft.getMinecraft().getRenderItem();
GlStateManager.pushMatrix();
RenderHelper.enableGUIStandardItemLighting();
GlStateManager.disableLighting();
GlStateManager.enableRescaleNormal();
GlStateManager.enableColorMaterial();
GlStateManager.enableLighting();
renderItem.zLevel = 100.0F;
if(!stack.isEmpty()){
renderItem.renderItemAndEffectIntoGUI(stack, x, y);
renderItem.renderItemOverlays(Minecraft.getMinecraft().fontRenderer, stack, x, y);
if(tooltip){
gui.drawHoveringText(gui.getItemToolTip(stack), mouseX + gui.getXSize()/2 - gui.width/2,
mouseY + gui.getYSize()/2 - gui.height/2);
}
}
GlStateManager.popMatrix();
GlStateManager.enableLighting();
GlStateManager.enableDepth();
RenderHelper.enableStandardItemLighting();
}
// Third person
@@ -241,7 +225,7 @@ public final class WizardryClientEventHandler {
GlStateManager.disableLighting();
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);
// Disabling depth test allows it to be seen through everything.
GL11.glDisable(GL11.GL_DEPTH_TEST);
GlStateManager.disableDepth();
GlStateManager.color(1, 1, 1, 1);
GlStateManager.translate(event.getX(), event.getY() + event.getEntity().height + 0.5, event.getZ());
@@ -265,7 +249,7 @@ public final class WizardryClientEventHandler {
GlStateManager.enableCull();
GlStateManager.enableLighting();
GL11.glEnable(GL11.GL_DEPTH_TEST);
GlStateManager.enableDepth();
GlStateManager.popMatrix();
}
@@ -282,7 +266,7 @@ public final class WizardryClientEventHandler {
GlStateManager.disableLighting();
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);
// Disabling depth test allows it to be seen through everything.
GL11.glDisable(GL11.GL_DEPTH_TEST);
GlStateManager.disableDepth();
GlStateManager.color(1, 1, 1, 1);
GlStateManager.translate(event.getX(), event.getY() + event.getEntity().height + 0.5, event.getZ());
@@ -306,7 +290,7 @@ public final class WizardryClientEventHandler {
GlStateManager.enableCull();
GlStateManager.enableLighting();
GL11.glEnable(GL11.GL_DEPTH_TEST);
GlStateManager.enableDepth();
GlStateManager.popMatrix();
}
@@ -327,7 +311,7 @@ public final class WizardryClientEventHandler {
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
// Disabling depth test allows it to be seen through everything.
GL11.glDisable(GL11.GL_DEPTH_TEST);
GlStateManager.disableDepth();
GlStateManager.translate(event.getX(), event.getY() + event.getEntity().height * 0.6, event.getZ());
@@ -351,7 +335,7 @@ public final class WizardryClientEventHandler {
GlStateManager.enableCull();
GlStateManager.disableBlend();
GlStateManager.enableLighting();
GL11.glEnable(GL11.GL_DEPTH_TEST);
GlStateManager.enableDepth();
GlStateManager.popMatrix();
}
@@ -365,8 +349,8 @@ public final class WizardryClientEventHandler {
GlStateManager.pushMatrix();
GL11.glDisable(GL11.GL_DEPTH_TEST);
GL11.glDepthMask(false);
GlStateManager.disableDepth();
GlStateManager.depthMask(false);
OpenGlHelper.glBlendFunc(770, 771, 1, 0);
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
GlStateManager.disableAlpha();
@@ -383,8 +367,8 @@ public final class WizardryClientEventHandler {
buffer.pos(0.0D, 0.0D, -90.0D).tex(0.0D, 0.0D).endVertex();
tessellator.draw();
GL11.glDepthMask(true);
GL11.glEnable(GL11.GL_DEPTH_TEST);
GlStateManager.depthMask(true);
GlStateManager.enableDepth();
GlStateManager.enableAlpha();
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
@@ -395,8 +379,8 @@ public final class WizardryClientEventHandler {
GlStateManager.pushMatrix();
GL11.glDisable(GL11.GL_DEPTH_TEST);
GL11.glDepthMask(false);
GlStateManager.disableDepth();
GlStateManager.depthMask(false);
OpenGlHelper.glBlendFunc(770, 771, 1, 0);
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
GlStateManager.disableAlpha();
@@ -413,8 +397,8 @@ public final class WizardryClientEventHandler {
buffer.pos(0.0D, 0.0D, -90.0D).tex(0.0D, 0.0D).endVertex();
tessellator.draw();
GL11.glDepthMask(true);
GL11.glEnable(GL11.GL_DEPTH_TEST);
GlStateManager.depthMask(true);
GlStateManager.enableDepth();
GlStateManager.enableAlpha();
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
@@ -1,10 +1,9 @@
package electroblob.wizardry.client.model;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.client.model.ModelRenderer;
import net.minecraft.entity.Entity;
public class ModelWizardArmour extends ModelBiped {
public class ModelWizardArmour extends ModelWtfMojang {
ModelRenderer Shape1;
ModelRenderer Shape2;
ModelRenderer Shape3;
@@ -0,0 +1,44 @@
package electroblob.wizardry.client.model;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityArmorStand;
public class ModelWtfMojang extends ModelBiped {
public ModelWtfMojang(float modelSize, float rotationYOffset, int textureWidth, int textureHeight) {
super(modelSize, rotationYOffset, textureWidth, textureHeight);
}
@Override
public void setRotationAngles(float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, float scaleFactor, Entity entityIn) {
// [VanillaCopy] ModelArmorStandArmor
// this prevents helmets from always facing south, and the armor "breathing" on the stand
if (entityIn instanceof EntityArmorStand) {
EntityArmorStand entityarmorstand = (EntityArmorStand) entityIn;
this.bipedHead.rotateAngleX = 0.017453292F * entityarmorstand.getHeadRotation().getX();
this.bipedHead.rotateAngleY = 0.017453292F * entityarmorstand.getHeadRotation().getY();
this.bipedHead.rotateAngleZ = 0.017453292F * entityarmorstand.getHeadRotation().getZ();
this.bipedHead.setRotationPoint(0.0F, 1.0F, 0.0F);
this.bipedBody.rotateAngleX = 0.017453292F * entityarmorstand.getBodyRotation().getX();
this.bipedBody.rotateAngleY = 0.017453292F * entityarmorstand.getBodyRotation().getY();
this.bipedBody.rotateAngleZ = 0.017453292F * entityarmorstand.getBodyRotation().getZ();
this.bipedLeftArm.rotateAngleX = 0.017453292F * entityarmorstand.getLeftArmRotation().getX();
this.bipedLeftArm.rotateAngleY = 0.017453292F * entityarmorstand.getLeftArmRotation().getY();
this.bipedLeftArm.rotateAngleZ = 0.017453292F * entityarmorstand.getLeftArmRotation().getZ();
this.bipedRightArm.rotateAngleX = 0.017453292F * entityarmorstand.getRightArmRotation().getX();
this.bipedRightArm.rotateAngleY = 0.017453292F * entityarmorstand.getRightArmRotation().getY();
this.bipedRightArm.rotateAngleZ = 0.017453292F * entityarmorstand.getRightArmRotation().getZ();
this.bipedLeftLeg.rotateAngleX = 0.017453292F * entityarmorstand.getLeftLegRotation().getX();
this.bipedLeftLeg.rotateAngleY = 0.017453292F * entityarmorstand.getLeftLegRotation().getY();
this.bipedLeftLeg.rotateAngleZ = 0.017453292F * entityarmorstand.getLeftLegRotation().getZ();
this.bipedLeftLeg.setRotationPoint(1.9F, 11.0F, 0.0F);
this.bipedRightLeg.rotateAngleX = 0.017453292F * entityarmorstand.getRightLegRotation().getX();
this.bipedRightLeg.rotateAngleY = 0.017453292F * entityarmorstand.getRightLegRotation().getY();
this.bipedRightLeg.rotateAngleZ = 0.017453292F * entityarmorstand.getRightLegRotation().getZ();
this.bipedRightLeg.setRotationPoint(-1.9F, 11.0F, 0.0F);
copyModelAngles(this.bipedHead, this.bipedHeadwear);
} else super.setRotationAngles(limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scaleFactor, entityIn);
}
}
@@ -143,7 +143,6 @@ public abstract class ParticleCustomTexture extends Particle {
float rotationYZ, float rotationXY, float rotationXZ){
GlStateManager.pushMatrix();
GlStateManager.pushAttrib();
this.applyGLStateChanges();
@@ -193,7 +192,6 @@ public abstract class ParticleCustomTexture extends Particle {
this.undoGLStateChanges();
GlStateManager.popAttrib();
GlStateManager.popMatrix();
}
@@ -40,7 +40,7 @@ public class RenderMagicLight extends TileEntitySpecialRenderer<TileEntityMagicL
GlStateManager.scale((float)tileentity.timer / 10, (float)tileentity.timer / 10,
(float)tileentity.timer / 10);
}
if(tileentity.timer > tileentity.maxTimer - 10){
if(tileentity.timer > tileentity.maxTimer - 10 && tileentity.timer <= tileentity.maxTimer){
GlStateManager.scale((float)(tileentity.maxTimer - tileentity.timer) / 10,
(float)(tileentity.maxTimer - tileentity.timer) / 10,
(float)(tileentity.maxTimer - tileentity.timer) / 10);
@@ -92,24 +92,20 @@ public class CommandViewAllies extends CommandBase {
if(WizardData.get(player) != null){
String string = "";
Object playerList = null;
Set<String> names = WizardData.get(player).allyNames;
if(!names.isEmpty()){
for(String name : names){
string = string + name + ", ";
}
// Cuts the last " ," off of the string.
string = string.substring(0, string.length() - 2);
playerList = joinNiceStringFromCollection(names);
}else{
string = I18n.format("commands." + Wizardry.MODID + ":allies.none");
playerList = new TextComponentTranslation("commands." + Wizardry.MODID + ":allies.none");
}
if(executeAsOtherPlayer){
sender.sendMessage(
new TextComponentTranslation("commands." + Wizardry.MODID + ":allies.list_other", player.getName(), string));
new TextComponentTranslation("commands." + Wizardry.MODID + ":allies.list_other", player.getName(), playerList));
}else{
sender.sendMessage(new TextComponentTranslation("commands." + Wizardry.MODID + ":allies.list", string));
sender.sendMessage(new TextComponentTranslation("commands." + Wizardry.MODID + ":allies.list", playerList));
}
}
}
@@ -1,7 +1,9 @@
package electroblob.wizardry.enchantment;
import java.util.Iterator;
import java.util.Map;
import com.google.common.collect.Iterables;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.registry.WizardryEnchantments;
import electroblob.wizardry.spell.FreezingWeapon;
@@ -10,11 +12,15 @@ import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.init.Items;
import net.minecraft.inventory.ContainerChest;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemBow;
import net.minecraft.item.ItemEnchantedBook;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.event.entity.item.ItemTossEvent;
import net.minecraftforge.event.entity.living.LivingDropsEvent;
@@ -55,11 +61,18 @@ public interface Imbuement {
if(stack.isItemEnchanted()){
// No need to check what enchantments the item has, since remove() does nothing if the element does not
// exist.
Map<Enchantment, Integer> enchantments = EnchantmentHelper.getEnchantments(stack);
// Removes the magic weapon enchantments from the enchantment map
enchantments.entrySet().removeIf(entry -> entry.getKey() instanceof Imbuement);
// Applies the new enchantment map to the item
EnchantmentHelper.setEnchantments(enchantments, stack);
NBTTagList enchantmentList = stack.getItem() == Items.ENCHANTED_BOOK ?
ItemEnchantedBook.getEnchantments(stack) : stack.getEnchantmentTagList();
// Check all enchantments of the item
Iterator<NBTBase> enchantmentIt = enchantmentList.iterator();
while(enchantmentIt.hasNext()){
NBTTagCompound enchantmentTag = (NBTTagCompound) enchantmentIt.next();
Enchantment enchantment = Enchantment.getEnchantmentByID(enchantmentTag.getShort("id"));
// If the item contains a magic weapon enchantment, remove it from the item
if(enchantment instanceof Imbuement){
enchantmentIt.remove();
}
}
}
}
@@ -70,18 +83,23 @@ public interface Imbuement {
// Still not sure if it's better to set stacks in slots or modify the itemstack list directly, but I would
// imagine it's the former.
for(Slot slot : event.getContainer().inventorySlots){
if(slot.getStack().getItem() instanceof ItemEnchantedBook){
ItemStack slotStack = slot.getStack();
if(slotStack.getItem() instanceof ItemEnchantedBook){
// We don't care about the level of the enchantments
Map<Enchantment, Integer> enchantments = EnchantmentHelper.getEnchantments(slot.getStack());
NBTTagList enchantmentList = ItemEnchantedBook.getEnchantments(slotStack);
// Removes all imbuements
if(enchantments.keySet().removeIf(e -> e instanceof Imbuement)){
// If any imbuements were removed, replaces the enchantments on the book with the new ones, or
// deletes the book entirely if there are none left.
if(enchantments.isEmpty()){
if(Iterables.removeIf(enchantmentList, tag -> {
NBTTagCompound enchantmentTag = (NBTTagCompound) tag;
return Enchantment.getEnchantmentByID(enchantmentTag.getShort("id"))
instanceof Imbuement;
})){
// If any imbuements were removed, inform about the removal of the enchantment(s), or
// delete the book entirely if there are none left.
if(enchantmentList.isEmpty()){
slot.putStack(ItemStack.EMPTY); // NOTE: Will need changing in 1.11
Wizardry.logger.info("Deleted enchanted book with illegal enchantments");
}else{
EnchantmentHelper.setEnchantments(enchantments, slot.getStack());
// Inform about enchantment removal
Wizardry.logger.info("Removed illegal enchantments from enchanted book");
}
}
@@ -3,7 +3,6 @@ package electroblob.wizardry.entity.living;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import com.google.common.base.Predicate;
@@ -118,10 +117,10 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity
|| (entity instanceof ISummonedCreature || entity instanceof EntityWizard
// ... or in the whitelist ...
|| Arrays.asList(Wizardry.settings.summonedCreatureTargetsWhitelist)
.contains(EntityList.getEntityString(entity).toLowerCase(Locale.ROOT)))
.contains(EntityList.getKey(entity.getClass())))
// ... and isn't in the blacklist ...
&& !Arrays.asList(Wizardry.settings.summonedCreatureTargetsBlacklist)
.contains(EntityList.getEntityString(entity).toLowerCase(Locale.ROOT))){
.contains(EntityList.getKey(entity.getClass()))){
// ... it can be attacked.
return true;
}
@@ -266,6 +265,21 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity
(NBTTagInt tag) -> Spell.get(tag.getInt()));
this.hasTower = nbt.getBoolean("hasTower");
}
@Override
public int getMaxSpawnedInChunk(){
return 1;
}
@Override
public boolean getCanSpawnHere(){
// Evil wizards can only spawn in the specified dimensions
for(int id : Wizardry.settings.evilWizardDimensions){
if(this.dimension == id) return super.getCanSpawnHere();
}
return false;
}
@Override
protected boolean canDespawn(){
@@ -17,6 +17,7 @@ import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraft.util.text.translation.I18n;
@@ -51,13 +52,22 @@ public class EntitySpiritHorse extends EntityHorse {
}
@Override
protected int getExperiencePoints(EntityPlayer p_70693_1_){
protected int getExperiencePoints(EntityPlayer player){
return 0;
}
@Override
protected Item getDropItem(){
protected boolean canDropLoot(){
return false;
}
@Override
protected Item getDropItem(){
return null;
}
@Override
protected ResourceLocation getLootTable(){
return null;
}
@@ -24,6 +24,7 @@ import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraft.world.DifficultyInstance;
@@ -70,11 +71,6 @@ public class EntitySpiritWolf extends EntityWolf {
super.onDeath(source);
}
@Override
protected int getExperiencePoints(EntityPlayer p_70693_1_){
return 0;
}
@Override
public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, IEntityLivingData livingdata){
@@ -147,11 +143,26 @@ public class EntitySpiritWolf extends EntityWolf {
return null;
}
@Override
protected int getExperiencePoints(EntityPlayer player){
return 0;
}
@Override
protected boolean canDropLoot(){
return false;
}
@Override
protected Item getDropItem(){
return null;
}
@Override
protected ResourceLocation getLootTable(){
return null;
}
@Override
public ITextComponent getDisplayName(){
if(getOwner() != null){
@@ -5,10 +5,11 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Random;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.base.Predicate;
import electroblob.wizardry.Wizardry;
@@ -28,25 +29,24 @@ import electroblob.wizardry.util.WizardryParticleType;
import electroblob.wizardry.util.WizardryUtilities;
import io.netty.buffer.ByteBuf;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityAgeable;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.IEntityLivingData;
import net.minecraft.entity.IMerchant;
import net.minecraft.entity.INpc;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIBase;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAILookAtTradePlayer;
import net.minecraft.entity.ai.EntityAIMoveTowardsRestriction;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAIOpenDoor;
import net.minecraft.entity.ai.EntityAIRestrictOpenDoor;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAITradePlayer;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.ai.EntityAIWatchClosest2;
import net.minecraft.entity.effect.EntityLightningBolt;
import net.minecraft.entity.monster.IMob;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
@@ -76,23 +76,12 @@ import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
import net.minecraftforge.fml.common.registry.VillagerRegistry.VillagerProfession;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.oredict.OreDictionary;
@Mod.EventBusSubscriber
public class EntityWizard extends EntityVillager implements ISpellCaster, IEntityAdditionalSpawnData {
/* After much debugging, the error in the compiled mod (outside of eclipse) was traced back to this class,
* specifically the methods copied in from EntityVillager when I changed this class to extend it. This figures,
* since I had 1.2.1 working just fine before I did that, and it was the only thing I changed. Apparently, methods
* and fields with obfuscated names like func_129090_a can cause problems when compiled. One of the ones here was
* renamed and the other deleted since it was never called. Watch out for this in future (unless, of course, they
* are overriding something, in which case it should be fine). */
// Extending EntityVillager turned out to be a pretty neat thing to do, since now zombies will attack wizards
// TODO: Perhaps we should be implementing IMerchant now instead?
public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISpellCaster, IEntityAdditionalSpawnData {
private EntityAIAttackSpell spellCastingAI = new EntityAIAttackSpell(this, 0.5D, 14.0F, 30, 50);
@@ -101,19 +90,21 @@ public class EntityWizard extends EntityVillager implements ISpellCaster, IEntit
/** The entity selector passed into the new AI methods. */
protected Predicate<Entity> targetSelector;
/** Copy of EntityVillager's buyingList, renamed to avoid confusion. */
/** The wizard's trades. */
private MerchantRecipeList trades;
/** The wizard's current customer. */
@Nullable
private EntityPlayer customer;
private int timeUntilReset;
/** addDefaultEquipmentAndRecipies is called if this is true */
private boolean updateRecipes;
/** Data parameter for the cooldown time for wizards healing themselves. */
private static final DataParameter<Integer> HEAL_COOLDOWN = EntityDataManager.createKey(EntityWizard.class,
DataSerializers.VARINT);
private static final DataParameter<Integer> HEAL_COOLDOWN = EntityDataManager.createKey(EntityWizard.class, DataSerializers.VARINT);
/** Data parameter for the wizard's element. */
private static final DataParameter<Integer> ELEMENT = EntityDataManager.createKey(EntityWizard.class,
DataSerializers.VARINT);
private static final DataParameter<Integer> ELEMENT = EntityDataManager.createKey(EntityWizard.class, DataSerializers.VARINT);
// Field implementations
private List<Spell> spells = new ArrayList<Spell>(4);
@@ -140,6 +131,8 @@ public class EntityWizard extends EntityVillager implements ISpellCaster, IEntit
protected void initEntityAI(){
this.tasks.addTask(0, new EntityAISwimming(this));
// Why would you go to the effort of making the IMerchant interface and then have the AI classes only accept
// EntityVillager? N
this.tasks.addTask(1, new EntityAITradePlayer(this));
this.tasks.addTask(1, new EntityAILookAtTradePlayer(this));
this.tasks.addTask(4, new EntityAIRestrictOpenDoor(this));
@@ -162,10 +155,10 @@ public class EntityWizard extends EntityVillager implements ISpellCaster, IEntit
if((entity instanceof IMob || entity instanceof ISummonedCreature
// ... or in the whitelist ...
|| Arrays.asList(Wizardry.settings.summonedCreatureTargetsWhitelist)
.contains(EntityList.getEntityString(entity).toLowerCase(Locale.ROOT)))
.contains(EntityList.getKey(entity.getClass())))
// ... and isn't in the blacklist ...
&& !Arrays.asList(Wizardry.settings.summonedCreatureTargetsBlacklist)
.contains(EntityList.getEntityString(entity).toLowerCase(Locale.ROOT))){
.contains(EntityList.getKey(entity.getClass()))){
// ... it can be attacked.
return true;
}
@@ -223,6 +216,55 @@ public class EntityWizard extends EntityVillager implements ISpellCaster, IEntit
return this.continuousSpell;
}
@Override
public void setCustomer(EntityPlayer player){
this.customer = player;
}
@Override
public EntityPlayer getCustomer(){
return this.customer;
}
public boolean isTrading(){
return this.getCustomer() != null;
}
@Override
public void verifySellingItem(ItemStack stack){
// Copied from EntityVillager
if(!this.world.isRemote && this.livingSoundTime > -this.getTalkInterval() + 20){
this.livingSoundTime = -this.getTalkInterval();
this.playSound(stack.isEmpty() ? SoundEvents.ENTITY_VILLAGER_NO : SoundEvents.ENTITY_VILLAGER_YES, this.getSoundVolume(), this.getSoundPitch());
}
}
@Override
public World getWorld(){
return this.world;
}
@Override
public BlockPos getPos(){
return new BlockPos(this);
}
@Override
@SideOnly(Side.CLIENT)
public void setRecipes(MerchantRecipeList recipeList){
// Apparently nothing goes here, and nothing's here in EntityVillager either...
}
@Override
public ITextComponent getDisplayName(){
return this.getElement().getWizardName();
}
@Override
protected boolean canDespawn(){
return false;
}
@Override
public void onLivingUpdate(){
@@ -303,8 +345,7 @@ public class EntityWizard extends EntityVillager implements ISpellCaster, IEntit
}
}
// Super call removed because EntityVillager's version does things I don't want and the next one up is
// in EntityLivingBase and does nothing.
super.updateAITasks(); // This actually does nothing
}
@Override
@@ -340,11 +381,6 @@ public class EntityWizard extends EntityVillager implements ISpellCaster, IEntit
}
}
@Override
public ITextComponent getDisplayName(){
return this.getElement().getWizardName();
}
@Override
public void writeEntityToNBT(NBTTagCompound nbt){
@@ -383,16 +419,6 @@ public class EntityWizard extends EntityVillager implements ISpellCaster, IEntit
nbt.getTagList("towerBlocks", NBT.TAG_LONG), (NBTTagLong tag) -> BlockPos.fromLong(tag.getLong())));
}
@Override
protected boolean canDespawn(){
return false;
}
@Override
public boolean isTrading(){
return this.getCustomer() != null;
}
@Override
public void useRecipe(MerchantRecipe merchantrecipe){
@@ -661,11 +687,6 @@ public class EntityWizard extends EntityVillager implements ISpellCaster, IEntit
return new ItemStack(Blocks.STONE);
}
@Override
public void setProfession(VillagerProfession prof){
// Disables Forge's stuff.
}
@Override
public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, IEntityLivingData livingdata){
@@ -823,49 +844,72 @@ public class EntityWizard extends EntityVillager implements ISpellCaster, IEntit
}
}
}
// Copied from their respective AI classes
public static class EntityAILookAtTradePlayer extends EntityAIWatchClosest {
private final EntityWizard wizard;
// EntityVillager overrides (that don't add features)
public EntityAILookAtTradePlayer(EntityWizard wizard){
super(wizard, EntityPlayer.class, 8.0F);
this.wizard = wizard;
}
@Override
public boolean isMating(){
return false;
@Override
public boolean shouldExecute(){
if(this.wizard.isTrading()){
this.closestEntity = this.wizard.getCustomer();
return true;
}else{
return false;
}
}
}
public static class EntityAITradePlayer extends EntityAIBase {
private final EntityWizard wizard;
@Override
public void setMating(boolean p_70947_1_){
}
public EntityAITradePlayer(EntityWizard wizard){
this.wizard = wizard;
this.setMutexBits(5);
}
@Override
public void setPlaying(boolean p_70939_1_){
}
@Override
public boolean shouldExecute(){
if(!this.wizard.isEntityAlive()){
return false;
}else if(this.wizard.isInWater()){
return false;
}else if(!this.wizard.onGround){
return false;
}else if(this.wizard.velocityChanged){
return false;
}else{
EntityPlayer entityplayer = this.wizard.getCustomer();
@Override
public boolean isPlaying(){
return false;
}
if(entityplayer == null){
return false;
}else if(this.wizard.getDistanceSq(entityplayer) > 16.0D){
return false;
}else{
return entityplayer.openContainer != null;
}
}
}
@Override
public void setLookingForHome(){
}
@Override
public void startExecuting(){
this.wizard.getNavigator().clearPath();
}
// Doesn't say it, but this is in fact nullable.
@Override
public EntityVillager createChild(EntityAgeable par1EntityAgeable){
return null;
}
@SideOnly(Side.CLIENT)
@Override
public void setRecipes(MerchantRecipeList par1MerchantRecipeList){
}
@Override
public void onStruckByLightning(EntityLightningBolt lightningBolt){
// Restores the normal behaviour, replacing EntityVillager's witch conversion.
this.attackEntityFrom(DamageSource.LIGHTNING_BOLT, 5.0F);
// Entity's version does something strange with the private fire variable, but since I don't have access this
// will probably be fine.
this.setFire(8);
@Override
public void resetTask(){
this.wizard.setCustomer((EntityPlayer)null);
}
}
}
@@ -2,7 +2,6 @@ package electroblob.wizardry.entity.living;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.Locale;
import java.util.UUID;
import javax.annotation.Nullable;
@@ -182,18 +181,28 @@ public interface ISummonedCreature extends IEntityAdditionalSpawnData {
if(!entity.isInvisible() && isValidTarget(entity)){
// ... and is a player, they can be attacked, since players can't be in the whitelist or the
// blacklist.
if(entity instanceof EntityPlayer) return true;
// blacklist ...
if(entity instanceof EntityPlayer){
// ... unless the creature was summoned by a good wizard who the player has not angered.
if(getCaster() instanceof EntityWizard){
if(((EntityWizard)getCaster()).getRevengeTarget() != entity
&& ((EntityWizard)getCaster()).getAttackTarget() != entity) {
return false;
}
}
return true;
}
// ... and is a mob, a summoned creature, a wizard ...
if((entity instanceof IMob || entity instanceof ISummonedCreature
|| (entity instanceof EntityWizard && !(getCaster() instanceof EntityWizard))
// ... or in the whitelist ...
|| Arrays.asList(Wizardry.settings.summonedCreatureTargetsWhitelist)
.contains(EntityList.getEntityString(entity).toLowerCase(Locale.ROOT)))
.contains(EntityList.getKey(entity.getClass())))
// ... and isn't in the blacklist ...
&& !Arrays.asList(Wizardry.settings.summonedCreatureTargetsBlacklist)
.contains(EntityList.getEntityString(entity).toLowerCase(Locale.ROOT))){
.contains(EntityList.getKey(entity.getClass()))){
// ... it can be attacked.
return true;
}
@@ -4,7 +4,6 @@ import io.netty.buffer.ByteBuf;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
/**
* Same as {@link EntityMagicProjectile}, but with an additional blast multiplier field which is synced and saved to
@@ -13,7 +12,7 @@ import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
* @author Electroblob
* @since Wizardry 1.2
*/
public abstract class EntityBomb extends EntityMagicProjectile implements IEntityAdditionalSpawnData {
public abstract class EntityBomb extends EntityMagicProjectile {
/** The entity blast multiplier. This is now synced and saved centrally from {@link EntityBomb}. */
public float blastMultiplier = 1.0f;
@@ -38,11 +37,13 @@ public abstract class EntityBomb extends EntityMagicProjectile implements IEntit
@Override
public void writeSpawnData(ByteBuf buffer){
buffer.writeFloat(blastMultiplier);
super.writeSpawnData(buffer);
}
@Override
public void readSpawnData(ByteBuf buffer){
blastMultiplier = buffer.readFloat();
super.readSpawnData(buffer);
}
@Override
@@ -434,7 +434,7 @@ public abstract class EntityMagicArrow extends Entity implements IProjectile, IE
this.onBlockHit();
if(this.stuckInBlock.getMaterial() != Material.AIR){
this.stuckInBlock.getBlock().onEntityCollidedWithBlock(this.world, raytraceresult.getBlockPos(),
this.stuckInBlock.getBlock().onEntityCollision(this.world, raytraceresult.getBlockPos(),
this.stuckInBlock, this);
}
}
@@ -1,7 +1,6 @@
package electroblob.wizardry.entity.projectile;
import java.util.List;
import io.netty.buffer.ByteBuf;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.projectile.EntityThrowable;
@@ -25,7 +24,7 @@ import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
* @author Electroblob
* @see EntityBomb
*/
public abstract class EntityMagicProjectile extends EntityThrowable {
public abstract class EntityMagicProjectile extends EntityThrowable implements IEntityAdditionalSpawnData {
public float damageMultiplier = 1.0f;
@@ -42,6 +41,8 @@ public abstract class EntityMagicProjectile extends EntityThrowable {
// This is the standard set of parameters for this method, used by snowballs and ender pearls amongst others.
this.shoot(thrower, thrower.rotationPitch, thrower.rotationYaw, 0.0f, this.getSpeed(), 1.0f);
this.damageMultiplier = damageMultiplier;
// Mojang's 'fix' for the projectile-hitting-thrower bug actually made the problem worse, hence the following line.
this.ignoreEntity = thrower;
}
public EntityMagicProjectile(World world, double x, double y, double z){
@@ -78,17 +79,17 @@ public abstract class EntityMagicProjectile extends EntityThrowable {
// inside a mob using commands, it wouldn't hit that mob. This is so minor that it's not worth sending a packet
// for, though it may become more noticeable if spells firing from blocks are added.
// TODO: Investigate whether this is still necessary in 1.12
if(this.world.isRemote){
List<Entity> list = this.world.getEntitiesWithinAABBExcludingEntity(this, this.getEntityBoundingBox().expand(this.motionX, this.motionY, this.motionZ).grow(1.0D));
for(Entity entity : list){ // Why does vanilla still not use a for-each loop?
if(entity.canBeCollidedWith() && this.ticksExisted < 2 && this.ignoreEntity == null){
this.ignoreEntity = entity;
}
}
// Pretty sure EntityThrowable handles the rest.
}
// if(this.world.isRemote){
//
// List<Entity> list = this.world.getEntitiesWithinAABBExcludingEntity(this, this.getEntityBoundingBox().expand(this.motionX, this.motionY, this.motionZ).grow(1.0D));
//
// for(Entity entity : list){ // Why does vanilla still not use a for-each loop?
// if(entity.canBeCollidedWith() && this.ticksExisted < 2 && this.ignoreEntity == null){
// this.ignoreEntity = entity;
// }
// }
// // Pretty sure EntityThrowable handles the rest.
// }
super.onUpdate();
}
@@ -105,4 +106,21 @@ public abstract class EntityMagicProjectile extends EntityThrowable {
nbttagcompound.setFloat("damageMultiplier", damageMultiplier);
}
@Override
// For now, we're only writing when the thrower exists, so subclasses MUST CALL SUPER LAST.
// TODO: Figure out whether there's a default value we can write that is never used as an entity id (0? -1? +/-MAX_VALUE?)
public void writeSpawnData(ByteBuf data){
if(this.getThrower() != null) data.writeInt(this.getThrower().getEntityId());
}
@Override
// For now, we're only writing when the thrower exists, so subclasses MUST CALL SUPER LAST.
public void readSpawnData(ByteBuf data){
if(data.isReadable()){
Entity entity = this.world.getEntityByID(data.readInt());
if(entity instanceof EntityLivingBase) this.thrower = (EntityLivingBase)entity;
this.ignoreEntity = this.thrower;
}
}
}
@@ -9,7 +9,6 @@ import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
import electroblob.wizardry.util.WizardryParticleType;
import electroblob.wizardry.util.WizardryUtilities;
import io.netty.buffer.ByteBuf;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
@@ -20,9 +19,6 @@ import net.minecraft.world.World;
public class EntitySparkBomb extends EntityBomb {
/** For client use, because thrower field is not visible. */
private int casterID;
public EntitySparkBomb(World par1World){
super(par1World);
}
@@ -84,7 +80,7 @@ public class EntitySparkBomb extends EntityBomb {
&& ((EntityPlayer)targets.get(i)).capabilities.isCreativeMode);
// Detects (client side) if target is the thrower, to stop particles being spawned around them.
if(flag && world.isRemote && targets.get(i).getEntityId() == this.casterID) flag = false;
//if(flag && world.isRemote && targets.get(i).getEntityId() == this.casterID) flag = false;
if(flag){
@@ -120,16 +116,4 @@ public class EntitySparkBomb extends EntityBomb {
this.setDead();
}
@Override
public void writeSpawnData(ByteBuf data){
super.writeSpawnData(data);
data.writeInt(this.getThrower().getEntityId());
}
@Override
public void readSpawnData(ByteBuf data){
super.readSpawnData(data);
this.casterID = data.readInt();
}
}
@@ -1,6 +1,10 @@
package electroblob.wizardry.item;
import java.util.List;
import java.util.UUID;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.constants.Constants;
@@ -8,20 +12,19 @@ import electroblob.wizardry.constants.Element;
import electroblob.wizardry.registry.WizardryAdvancementTriggers;
import electroblob.wizardry.registry.WizardryTabs;
import electroblob.wizardry.spell.Petrify;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.EnumAction;
import net.minecraft.item.ItemArmor;
import net.minecraft.item.ItemStack;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumHandSide;
import net.minecraft.world.World;
import net.minecraftforge.common.ISpecialArmor;
import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
@@ -29,8 +32,13 @@ import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@Mod.EventBusSubscriber
public class ItemWizardArmour extends ItemArmor implements ISpecialArmor {
public class ItemWizardArmour extends ItemArmor {
//VanillaCopy, ItemArmor has this set to private for some reason.
public static final UUID[] ARMOR_MODIFIERS = new UUID[] {UUID.fromString("845DB27C-C624-495F-8C9F-6020A9A58B6B"), UUID.fromString("D8499B04-0E66-4726-AB29-64469D734E0D"), UUID.fromString("9F3D476D-C118-4544-8365-64846904B48E"), UUID.fromString("2AD3F246-FEE1-4E67-B886-69FD380BB150")};
//Damage reduction values that used to be in WizardryItems.SILK [feet, legs, chest, head]
private static int[] reductions = new int[]{2, 4, 5, 2};
public Element element;
public ItemWizardArmour(ArmorMaterial material, int renderIndex, EntityEquipmentSlot armourType, Element element){
@@ -149,73 +157,41 @@ public class ItemWizardArmour extends ItemArmor implements ISpecialArmor {
public boolean getIsRepairable(ItemStack stack, ItemStack par2ItemStack){
return false;
}
@Override
public ArmorProperties getProperties(EntityLivingBase player, ItemStack armor, DamageSource source, double damage,
int slotIndex){
EntityEquipmentSlot slot = getArmorSlotFromIndex(slotIndex);
if(!source.isUnblockable() && armor.getItemDamage() < armor.getMaxDamage()){
if(armor.hasTagCompound() && armor.getTagCompound().getBoolean("legendary")){
// Legendary armour gives full 10 shields, like diamond.
return new ArmorProperties(0, ArmorMaterial.DIAMOND.getDamageReductionAmount(slot) / 25D,
armor.getMaxDamage() + 1 - armor.getItemDamage());
}else{
return new ArmorProperties(0, this.damageReduceAmount / 25D,
armor.getMaxDamage() + 1 - armor.getItemDamage());
}
}else{
return new ArmorProperties(0, 0, 0);
}
}
@Override
public int getArmorDisplay(EntityPlayer player, ItemStack armor, int slotIndex){
EntityEquipmentSlot slot = getArmorSlotFromIndex(slotIndex);
if(armor.getItemDamage() < armor.getMaxDamage()){
if(armor.hasTagCompound() && armor.getTagCompound().getBoolean("legendary")){
// Legendary armour gives full 10 shields, like diamond.
return ArmorMaterial.DIAMOND.getDamageReductionAmount(slot);
}else{
return this.getArmorMaterial().getDamageReductionAmount(slot);
}
}else{
return 0;
}
}
@Override
public void damageArmor(EntityLivingBase entity, ItemStack stack, DamageSource source, int damage, int slot){
if(stack.getItemDamage() < stack.getMaxDamage()){
if(stack.getItemDamage() + damage > stack.getMaxDamage()){
// Note for reference: this is the method to use, despite how it sounds attemptDamageItem() is called
// by this one, not the other way round.
stack.damageItem(stack.getMaxDamage() - stack.getItemDamage(), entity);
}else{
stack.damageItem(damage, entity);
}
}
}
/**
* Returns the EntityEquipmentSlot for which index() returns an integer equal to the passed in slotIndex and which
* is an armour slot (not a hand slot). This only exists because the 1.10.2/1.11.2 versions of Forge still uses an
* integer slot index in ISpecialArmor instead of an EntityEquipmentSlot.
/*
* Properly handles the defense value of the armor. This method is responisble for the tooltip on top of
* the armor value. It is also what handles armor toughness, but the wizard armor had a value of 0 for that.
*/
// NOTE: Remove in 1.12.2
private EntityEquipmentSlot getArmorSlotFromIndex(int slotIndex){
// Had to pick something to begin with.
EntityEquipmentSlot slot = EntityEquipmentSlot.HEAD;
for(EntityEquipmentSlot s : WizardryUtilities.ARMOUR_SLOTS){
if(s.getIndex() == slotIndex){
slot = s;
@Override
public Multimap<String, AttributeModifier> getAttributeModifiers(EntityEquipmentSlot slot, ItemStack stack){
Multimap<String, AttributeModifier> map = HashMultimap.create();
if(stack.getItemDamage() < stack.getMaxDamage() && this.armorType == slot){
int defense = reductions[slot.getIndex()];
float toughness = 0f;
if(stack.hasTagCompound() && stack.getTagCompound().getBoolean("legendary")) {
defense = ArmorMaterial.DIAMOND.getDamageReductionAmount(slot);
toughness = ArmorMaterial.DIAMOND.getToughness();
}
map.put(SharedMonsterAttributes.ARMOR.getName(), new AttributeModifier(ARMOR_MODIFIERS[slot.getIndex()],
"Armor modifier", defense, 0));
map.put(SharedMonsterAttributes.ARMOR.getName(), new AttributeModifier(ARMOR_MODIFIERS[slot.getIndex()],
"Armor toughness", toughness, 0));
}
return slot;
return map;
}
// Fixes wizard armor breaking by disallowing setting damage above the max, since damageArmor is not always called.
// Since ISpecialArmor has been removed from this class, this may no longer be necessary, but keeping it won't hurt.
@Override
public void setDamage(ItemStack stack, int damage) {
if(damage <= stack.getMaxDamage()) super.setDamage(stack, damage);
else super.setDamage(stack, stack.getMaxDamage());
}
@SubscribeEvent
@@ -108,7 +108,7 @@ public class RandomSpell extends LootFunction {
}
}else{
// In theory, swapping this line to the commented one should make absolutely no difference.
element = elements.get(random.nextInt(tiers.size()));
element = elements.get(random.nextInt(elements.size()));
// element = null;
}
@@ -34,10 +34,6 @@ public class PacketSyncSettings implements IMessageHandler<Message, IMessage> {
}
private static void copySettings(Message message){
Wizardry.settings.firebombIsCraftable = message.settings.firebombIsCraftable;
Wizardry.settings.poisonBombIsCraftable = message.settings.poisonBombIsCraftable;
Wizardry.settings.smokeBombIsCraftable = message.settings.smokeBombIsCraftable;
Wizardry.settings.useAlternateScrollRecipe = message.settings.useAlternateScrollRecipe;
Wizardry.settings.discoveryMode = message.settings.discoveryMode;
// Wizardry.settings.maxSpellCommandMultiplier = message.settings.maxSpellCommandMultiplier;
// Wizardry.settings.castCommandName = message.settings.castCommandName;
@@ -65,10 +61,6 @@ public class PacketSyncSettings implements IMessageHandler<Message, IMessage> {
// This is also a great reason to have the settings as an actual object.
settings = new Settings();
// The order is important
settings.firebombIsCraftable = buf.readBoolean();
settings.poisonBombIsCraftable = buf.readBoolean();
settings.smokeBombIsCraftable = buf.readBoolean();
settings.useAlternateScrollRecipe = buf.readBoolean();
settings.discoveryMode = buf.readBoolean();
// settings.maxSpellCommandMultiplier = buf.readDouble();
// settings.castCommandName = ByteBufUtils.readUTF8String(buf);
@@ -79,10 +71,6 @@ public class PacketSyncSettings implements IMessageHandler<Message, IMessage> {
@Override
public void toBytes(ByteBuf buf){
buf.writeBoolean(settings.firebombIsCraftable);
buf.writeBoolean(settings.poisonBombIsCraftable);
buf.writeBoolean(settings.smokeBombIsCraftable);
buf.writeBoolean(settings.useAlternateScrollRecipe);
buf.writeBoolean(settings.discoveryMode);
// buf.writeDouble(settings.maxSpellCommandMultiplier);
// ByteBufUtils.writeUTF8String(buf, settings.castCommandName);
@@ -40,25 +40,18 @@ public final class WizardryBlocks {
// setSoundType should be public, but in this particular version it isn't... which is a bit of a pain.
public static final Block arcane_workbench = new BlockArcaneWorkbench().setHardness(1.0F)
.setCreativeTab(WizardryTabs.WIZARDRY);
public static final Block crystal_ore = new BlockCrystalOre(Material.ROCK).setHardness(3.0F)
.setCreativeTab(WizardryTabs.WIZARDRY);
public static final Block arcane_workbench = new BlockArcaneWorkbench().setHardness(1.0F).setCreativeTab(WizardryTabs.WIZARDRY);
public static final Block crystal_ore = new BlockCrystalOre(Material.ROCK).setHardness(3.0F).setCreativeTab(WizardryTabs.WIZARDRY);
public static final Block petrified_stone = new BlockStatue(Material.ROCK).setHardness(1.5F).setResistance(10.0F);
public static final Block ice_statue = new BlockStatue(Material.ICE).setHardness(0.5F).setLightOpacity(3);
public static final Block magic_light = new BlockMagicLight(Material.CIRCUITS);
public static final Block crystal_flower = new BlockCrystalFlower(Material.PLANTS).setHardness(0.0F)
.setCreativeTab(WizardryTabs.WIZARDRY);
public static final Block crystal_flower = new BlockCrystalFlower(Material.PLANTS).setHardness(0.0F).setCreativeTab(WizardryTabs.WIZARDRY);
public static final Block snare = new BlockSnare(Material.PLANTS).setHardness(0.0F);
public static final Block transportation_stone = new BlockTransportationStone(Material.ROCK).setHardness(0.0F)
.setLightLevel(0.5f).setLightOpacity(0).setCreativeTab(WizardryTabs.WIZARDRY);
public static final Block spectral_block = new BlockSpectral(Material.GLASS).setLightLevel(0.7f).setLightOpacity(0)
.setBlockUnbreakable().setResistance(6000000.0F);
public static final Block crystal_block = new Block(Material.IRON).setHardness(5.0F).setResistance(10.0F)
.setCreativeTab(WizardryTabs.WIZARDRY);
public static final Block transportation_stone = new BlockTransportationStone(Material.ROCK).setHardness(0.3F).setLightLevel(0.5f).setLightOpacity(0).setCreativeTab(WizardryTabs.WIZARDRY);
public static final Block spectral_block = new BlockSpectral(Material.GLASS).setLightLevel(0.7f).setLightOpacity(0).setBlockUnbreakable().setResistance(6000000.0F);
public static final Block crystal_block = new Block(Material.IRON).setHardness(5.0F).setResistance(10.0F).setCreativeTab(WizardryTabs.WIZARDRY);
public static final Block meteor = new Block(Material.ROCK).setLightLevel(1);
public static final Block vanishing_cobweb = new BlockVanishingCobweb(Material.WEB).setLightOpacity(1)
.setHardness(4.0F);
public static final Block vanishing_cobweb = new BlockVanishingCobweb(Material.WEB).setLightOpacity(1).setHardness(4.0F);
static{
// This is here because Block#setHarvestLevel isn't chainable.
@@ -77,7 +70,7 @@ public final class WizardryBlocks {
*/
public static void registerBlock(IForgeRegistry<Block> registry, Block block, String name){
block.setRegistryName(Wizardry.MODID, name);
block.setUnlocalizedName(block.getRegistryName().toString());
block.setTranslationKey(block.getRegistryName().toString());
registry.register(block);
}
@@ -127,7 +127,7 @@ public final class WizardryItems {
public static final Item armour_upgrade = new ItemArmourUpgrade();
public static final ArmorMaterial SILK = EnumHelper.addArmorMaterial("SILK",
"wizardry/textures/armour/wizard_armour", 15, new int[]{2, 5, 4, 2}, 0,
"wizardry/textures/armour/wizard_armour", 15, new int[]{0, 0, 0, 0}, 0,
SoundEvents.ITEM_ARMOR_EQUIP_LEATHER, 0.0F);
// Saw a post somewhere that said you have to put these in the init methods rather than defining them as constants.
@@ -271,7 +271,7 @@ public final class WizardryItems {
*/
public static void registerItem(IForgeRegistry<Item> registry, Item item, String name){
item.setRegistryName(Wizardry.MODID, name);
item.setUnlocalizedName(item.getRegistryName().toString());
item.setTranslationKey(item.getRegistryName().toString());
registry.register(item);
}
@@ -73,11 +73,10 @@ import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EnumCreatureType;
import net.minecraft.init.Biomes;
import net.minecraft.init.Items;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.FurnaceRecipes;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.storage.loot.LootTableList;
@@ -89,7 +88,6 @@ import net.minecraftforge.fml.common.registry.EntityRegistry;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.oredict.OreDictionary;
import net.minecraftforge.oredict.ShapedOreRecipe;
import net.minecraftforge.oredict.ShapelessOreRecipe;
import net.minecraftforge.registries.IForgeRegistry;
@@ -245,53 +243,18 @@ public final class WizardryRegistry {
EntityRegistry.registerEgg(registryName, eggColour, spotColour);
}
/** Called from the init method in the main mod class to register all the recipes. */
/** Now only deals with the dynamic crafting recipes and the smelting recipes. */
@SubscribeEvent
public static void registerRecipes(RegistryEvent.Register<IRecipe> event){
IForgeRegistry<IRecipe> registry = event.getRegistry();
ItemStack magicCrystalStack = new ItemStack(WizardryItems.magic_crystal);
ItemStack magicWandStack = new ItemStack(WizardryItems.magic_wand, 1, Tier.BASIC.maxCharge);
ItemStack goldNuggetStack = new ItemStack(Items.GOLD_NUGGET);
ItemStack stickStack = new ItemStack(Items.STICK);
ItemStack bookStack = new ItemStack(Items.BOOK);
ItemStack spellBookStack = new ItemStack(WizardryItems.spell_book, 1, Spells.magic_missile.id());
Ingredient crystalFlowerStack = Ingredient.fromStacks(new ItemStack(WizardryBlocks.crystal_flower));
ItemStack magicCrystalStack1 = new ItemStack(WizardryItems.magic_crystal, 2);
ItemStack magicCrystalStack2 = new ItemStack(WizardryItems.magic_crystal, 9);
Ingredient crystalBlockStack = Ingredient.fromStacks(new ItemStack(WizardryBlocks.crystal_block));
ItemStack manaFlaskStack = new ItemStack(WizardryItems.mana_flask);
Ingredient bottleStack = Ingredient.fromStacks(new ItemStack(Items.GLASS_BOTTLE));
Ingredient gunpowderStack = Ingredient.fromStacks(new ItemStack(Items.GUNPOWDER));
Ingredient blazePowderStack = Ingredient.fromStacks(new ItemStack(Items.BLAZE_POWDER));
Ingredient spiderEyeStack = Ingredient.fromStacks(new ItemStack(Items.SPIDER_EYE));
// Coal or charcoal is equally fine, hence the wildcard value
Ingredient coalStack = Ingredient.fromStacks(new ItemStack(Items.COAL, 1, OreDictionary.WILDCARD_VALUE));
ItemStack firebombStack = new ItemStack(WizardryItems.firebomb, 3);
ItemStack poisonBombStack = new ItemStack(WizardryItems.poison_bomb, 3);
ItemStack smokeBombStack = new ItemStack(WizardryItems.smoke_bomb, 3);
ItemStack scrollStack = new ItemStack(WizardryItems.blank_scroll);
Ingredient paperStack = Ingredient.fromStacks(new ItemStack(Items.PAPER));
Ingredient stringStack = Ingredient.fromStacks(new ItemStack(Items.STRING));
registry.register(new ShapedOreRecipe(null, magicWandStack, " x", " y ", "z ", 'x', magicCrystalStack, 'y', stickStack, 'z', goldNuggetStack).setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/magic_wand")));
registry.register(new ShapedOreRecipe(null, spellBookStack, " x ", "xyx", " x ", 'x', magicCrystalStack, 'y', bookStack).setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/spellbook")));
registry.register(new ShapelessOreRecipe(null, magicCrystalStack1, crystalFlowerStack).setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/magic_crystal_1")));
registry.register(new ShapelessOreRecipe(null, magicCrystalStack2, crystalBlockStack).setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/magic_crystal_2")));
if(Wizardry.settings.firebombIsCraftable) registry.register(new ShapelessOreRecipe(null, firebombStack, bottleStack, gunpowderStack, blazePowderStack, blazePowderStack).setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/fire_bomb")));
if(Wizardry.settings.poisonBombIsCraftable) registry.register(new ShapelessOreRecipe(null, poisonBombStack, bottleStack, gunpowderStack, spiderEyeStack, spiderEyeStack).setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/poison_bomb")));
if(Wizardry.settings.smokeBombIsCraftable) registry.register(new ShapelessOreRecipe(null, smokeBombStack, bottleStack, gunpowderStack, coalStack, coalStack).setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/smoke_bomb")));
if(Wizardry.settings.useAlternateScrollRecipe){
registry.register(new ShapelessOreRecipe(null, scrollStack, paperStack, stringStack, magicCrystalStack).setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/blank_scroll")));
}else{
registry.register(new ShapelessOreRecipe(null, scrollStack, paperStack, stringStack).setRegistryName(new ResourceLocation(Wizardry.MODID, "recipes/blank_scroll")));
}
FurnaceRecipes.instance().addSmeltingRecipeForBlock(WizardryBlocks.crystal_ore, new ItemStack(WizardryItems.magic_crystal), 0.5f);
// Mana flask recipes
ItemStack manaFlaskStack = new ItemStack(WizardryItems.mana_flask);
ItemStack miscWandStack;
for(Element element : Element.values()){
@@ -303,7 +266,6 @@ public final class WizardryRegistry {
}
}
ItemStack miscArmourStack;
for(Element element : Element.values()){
@@ -31,7 +31,7 @@ public final class WizardryTabs {
@Override
@SideOnly(Side.CLIENT)
public ItemStack getTabIconItem(){
public ItemStack createIcon(){
return new ItemStack(WizardryItems.wizard_handbook);
}
@@ -47,7 +47,7 @@ public final class WizardryTabs {
@Override
@SideOnly(Side.CLIENT)
public ItemStack getTabIconItem(){
public ItemStack createIcon(){
return new ItemStack(WizardryItems.spell_book);
}
@@ -149,7 +149,7 @@ public class IceAge extends Spell {
world.setBlockState(pos.down(), Blocks.OBSIDIAN.getDefaultState());
}else if(world.getBlockState(pos.down()) == Blocks.FLOWING_LAVA.getDefaultState()){
world.setBlockState(pos.down(), Blocks.COBBLESTONE.getDefaultState());
}else{
}else if(Blocks.SNOW_LAYER.canPlaceBlockAt(world, pos)){
world.setBlockState(pos, Blocks.SNOW_LAYER.getDefaultState());
}
}
@@ -1,5 +1,6 @@
package electroblob.wizardry.spell;
import java.util.Arrays;
import java.util.List;
import electroblob.wizardry.Wizardry;
@@ -14,6 +15,7 @@ import electroblob.wizardry.util.SpellModifiers;
import electroblob.wizardry.util.WizardryParticleType;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.INpc;
@@ -143,7 +145,8 @@ public class MindControl extends Spell {
/** Returns true if the given entity can be mind controlled (i.e. is not a player, npc, evil wizard or boss). */
public static boolean canControl(EntityLivingBase target){
return target instanceof EntityLiving && target.isNonBoss() && !(target instanceof INpc)
&& !(target instanceof EntityEvilWizard);
&& !(target instanceof EntityEvilWizard) && !Arrays.asList(Wizardry.settings.mindControlTargetsBlacklist)
.contains(EntityList.getKey(target.getClass()));
}
/**
@@ -200,11 +203,11 @@ public class MindControl extends Spell {
Entity caster = WizardryUtilities.getEntityByUUID(world, entityNBT.getUniqueId(MindControl.NBT_KEY));
// If the current target is already a valid mind control target, nothing happens.
if(WizardryUtilities.isValidTarget(caster, currentTarget)) return;
if(caster instanceof EntityLivingBase){
// If the current target is already a valid mind control target, nothing happens.
if(WizardryUtilities.isValidTarget(caster, currentTarget)) return;
if(MindControl.findMindControlTarget(entity, (EntityLivingBase)caster, world)){
// If it worked, skip setting the target to null.
return;
@@ -1,5 +1,6 @@
package electroblob.wizardry.spell;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -398,17 +399,16 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
*/
public static Spell get(String name){
ResourceLocation key = new ResourceLocation(name);
if(key.getResourceDomain().equals("minecraft")) key = new ResourceLocation(Wizardry.MODID, name);
if(key.getNamespace().equals("minecraft")) key = new ResourceLocation(Wizardry.MODID, name);
return ((ForgeRegistry<Spell>)registry).getValue(key);
}
/** Returns a list of all registered spells' registry names, excluding the 'none' spell. Used in commands. */
public static String[] getSpellNames(){
public static Collection<ResourceLocation> getSpellNames(){
// Maybe it would be better to store all of this statically?
Set<ResourceLocation> keys = new HashSet<ResourceLocation>(registry.getKeys());
keys.remove(registry.getKey(Spells.none));
// Streams!
return keys.stream().map(ResourceLocation::toString).toArray(String[]::new);
return keys;
}
/**
@@ -331,7 +331,7 @@ public class ContainerArcaneWorkbench extends Container {
// This needs to happen so the charging works on the new wand, not the old one.
wand = this.getSlot(WAND_SLOT).getStack();
}else{
}else if(WandHelper.isWandUpgrade(upgrade.getItem())){
// Special upgrades
@@ -28,6 +28,7 @@ import net.minecraftforge.fml.relauncher.SideOnly;
public class TileEntityArcaneWorkbench extends TileEntity implements IInventory, ITickable {
/** The inventory of the arcane workbench. */
private NonNullList<ItemStack> inventory;
/** Controls the rotation of the rune. */
public float timer = 0;
@@ -1,5 +1,6 @@
package electroblob.wizardry.tileentity;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.block.Block;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.EntityLiving;
@@ -107,8 +108,7 @@ public class TileEntityStatue extends TileEntity implements ITickable {
// Breaks the block at light levels of 7 or below, with a higher chance the lower the light level.
// The chance is (8 - light level)/12, so at light 0 the chance is 3/4 and at light 7 the chance is 1/12.
if(!this.world.isRemote && this.timer % 200 == 0 && this.timer > lifetime && !this.isIce && this.position == 1){
// TESTME: There are about 10 different light-related methods in world now... is this the right one?
if(this.world.getLight(pos) < this.world.rand.nextInt(12) - 3){
if(WizardryUtilities.getLightLevel(world, pos) < this.world.rand.nextInt(12) - 3){
// This is all that is needed because destroyBlock invokes the breakBlock function in
// BlockPetrifiedStone
// and that function handles all the spawning and stuff.
@@ -64,9 +64,9 @@ import net.minecraft.util.EntityDamageSource;
public class MagicDamage extends EntityDamageSource implements IElementalDamage {
/** The name of the damagesource for direct magic damage from the wizardry mod. */
public static final String DIRECT_MAGIC_DAMAGE = "wizardryMagic";
public static final String DIRECT_MAGIC_DAMAGE = "wizardry_magic";
/** The name of the damagesource for indirect magic damage from the wizardry mod. */
public static final String INDIRECT_MAGIC_DAMAGE = "indirectWizardryMagic";
public static final String INDIRECT_MAGIC_DAMAGE = "indirect_wizardry_magic";
// Technically, I don't need to specify that the classes in this map must extend entity, but it's good practice to.
private static final Map<Class<? extends Entity>, DamageType[]> immunityMapping = new HashMap<Class<? extends Entity>, DamageType[]>();
@@ -169,7 +169,7 @@ public class MagicDamage extends EntityDamageSource implements IElementalDamage
}
/**
* Returns a DamageSource called "wizardryMagic" with the given entity as the caster. Use in preference to vanilla
* Returns a DamageSource called "wizardry_magic" with the given entity as the caster. Use in preference to vanilla
* types to allow things to distinguish between magic and regular melee/swords. Unlike DamageSource.MAGIC, it does
* not bypass armour and has a player as the source (rather than nothing). It is still classed as magic damage (for
* the record, all this does in vanilla is make witches 85% resistant to it - but that seems kinda right anyway).
@@ -190,7 +190,7 @@ public class MagicDamage extends EntityDamageSource implements IElementalDamage
}
/**
* Returns a DamageSource called "wizardryMagic" with the given entity as the caster. Use in preference to vanilla
* Returns a DamageSource called "wizardry_magic" with the given entity as the caster. Use in preference to vanilla
* types to allow things to distinguish between magic and regular melee/swords. Unlike DamageSource.MAGIC, it does
* not bypass armour and has a player as the source (rather than nothing). It is still classed as magic damage (for
* the record, all this does in vanilla is make witches 85% resistant to it - but that seems kinda right anyway).
@@ -212,7 +212,7 @@ public class MagicDamage extends EntityDamageSource implements IElementalDamage
}
/**
* Returns a DamageSource called "indirectWizardryMagic" with the player as the caster. Use in preference to vanilla
* Returns a DamageSource called "indirect_wizardry_magic" with the player as the caster. Use in preference to vanilla
* types to allow things to distinguish between magic and regular arrows/throwables. Unlike
* DamageSource.causeIndirectMagicDamage, it does not bypass armour. It is still classed as magic damage (for the
* record, all this does in vanilla is make witches 85% resistant to it - but that seems kinda right anyway).
@@ -234,7 +234,7 @@ public class MagicDamage extends EntityDamageSource implements IElementalDamage
}
/**
* Returns a DamageSource called "indirectWizardryMagic" with the player as the caster. Use in preference to vanilla
* Returns a DamageSource called "indirect_wizardry_magic" with the player as the caster. Use in preference to vanilla
* types to allow things to distinguish between magic and regular arrows/throwables. Unlike
* DamageSource.causeIndirectMagicDamage, it does not bypass armour. It is still classed as magic damage (for the
* record, all this does in vanilla is make witches 85% resistant to it - but that seems kinda right anyway).
@@ -107,7 +107,7 @@ public final class WandHelper {
int selectedSpell = wand.getTagCompound().getInteger(SELECTED_SPELL_KEY);
if(selectedSpell < spells.length){
if(selectedSpell >= 0 && selectedSpell < spells.length){
return spells[selectedSpell];
}
}
@@ -98,6 +98,26 @@ public final class WizardryUtilities {
// SECTION Block/Entity/World Utilities
// ===============================================================================================================
/**
* Returns the actual light level, taking natural light (skylight) and artificial light (block light) into account.
* This uses the same logic as mob spawning.
*
* @return The light level, from 0 (pitch darkness) to 15 (full daylight/at a torch).
*/
public static int getLightLevel(World world, BlockPos pos){
int i = world.getLightFromNeighbors(pos);
if(world.isThundering()){
int j = world.getSkylightSubtracted();
world.setSkylightSubtracted(10);
i = world.getLightFromNeighbors(pos);
world.setSkylightSubtracted(j);
}
return i;
}
/**
* Returns whether the block at the given coordinates can be replaced by another one (works as if a block is being
* placed by a player). True for air, liquids, vines, tall grass and snow layers but not for flowers, signs etc.
@@ -520,7 +540,7 @@ public final class WizardryUtilities {
Vec3d start = new Vec3d(entity.posX, entity.getEntityBoundingBox().minY + entity.getEyeHeight(), entity.posZ);
Vec3d look = entity.getLookVec();
Vec3d end = start.addVector(look.x * range, look.y * range, look.z * range);
Vec3d end = start.add(look.x * range, look.y * range, look.z * range);
return world.rayTraceBlocks(start, end, hitLiquids);
}
@@ -873,7 +893,7 @@ public final class WizardryUtilities {
// The original tag list should remain unchanged, hence the copy.
NBTTagList tagList2 = (NBTTagList)tagList.copy();
while(!tagList2.hasNoTags()){
while(!tagList2.isEmpty()){
NBTBase tag = tagList2.removeTag(0);
// Why oh why is NBTTagList not parametrised? It even has a tagType field, so it must know!
try{
@@ -942,7 +962,7 @@ public final class WizardryUtilities {
*
* @return False under any of the following circumstances, true otherwise:
* <p>
* - Either entity is null
* - The target is null
* <p>
* - The target is the attacker (this isn't as stupid as it sounds - anything with an AoE might cause this
* to be true, as can summoned creatures)
@@ -951,10 +971,18 @@ public final class WizardryUtilities {
* attacker need not be an ally of the target)
* <p>
* - The target is a creature that was summoned/controlled by the attacker or by an ally of the attacker.
* <p>
* <i>As of wizardry 4.1.2, this method now returns <b>true</b> instead of false if the attacker is null. This
* is because in the vast majority of cases, it makes more sense this way: if a construct has no caster, it
* should affect all entities; if a minion has no caster is should target all entities; etc.</i>
*/
public static boolean isValidTarget(Entity attacker, Entity target){
if(attacker == null || target == null) return false;
// Always return true if the attacker is null
if(attacker == null) return true;
// Always return false if the target is null
if(target == null) return false;
// Tests whether the target is the attacker
if(target == attacker) return false;
@@ -655,20 +655,35 @@ commands.ebwizardry:discoverspell.removespell=Removed %1$s from %2$s's spell dis
config.ebwizardry.title.general=Mod Options
config.ebwizardry.category.spells=Configure Spells
config.ebwizardry.category.gameplay=Gameplay Settings
config.ebwizardry.category.gameplay.tooltip=Configure wizardry's general gameplay
config.ebwizardry.title.gameplay=Gameplay Settings
config.ebwizardry.subtitle.gameplay=Global settings that affect game mechanics.
config.ebwizardry.category.worldgen=World Generation Settings
config.ebwizardry.category.worldgen.tooltip=Configure wizardry's world generation features
config.ebwizardry.title.worldgen=World Generation Settings
config.ebwizardry.subtitle.worldgen=Settings that affect world generation.
config.ebwizardry.category.commands=Command Settings
config.ebwizardry.category.commands.tooltip=Configure wizardry's commands
config.ebwizardry.title.commands=Command Settings
config.ebwizardry.subtitle.commands=Settings for the commands added by Wizardry.
config.ebwizardry.category.client=Client Settings
config.ebwizardry.category.client.tooltip=Configure wizardry's display and controls
config.ebwizardry.title.client=Client Settings
config.ebwizardry.subtitle.client=Client-side settings that only affect the local minecraft game.
config.ebwizardry.category.spells=Spell Configuration
config.ebwizardry.category.spells.tooltip=Select which spells are enabled
config.ebwizardry.title.spells=Spell Configuration
config.ebwizardry.subtitle.spells=Set a spell to false to disable it.
config.ebwizardry.category.resistances=Configure Resistances
config.ebwizardry.category.resistances=Resistance Configuration
config.ebwizardry.category.resistances.tooltip=Configure which mobs are immune to different types of magic
config.ebwizardry.title.resistances=Resistance Configuration
config.ebwizardry.subtitle.resistances=See descriptions of individual options for more details.
config.ebwizardry.category.ids=Configure IDs
config.ebwizardry.category.ids.tooltip=Change the IDs used by wizardry
config.ebwizardry.title.ids=ID Configuration
config.ebwizardry.subtitle.ids=Change these IDs if they conflict with another mod.
config.ebwizardry.subtitle.resistances=Settings which allow entities to be made immune to certain types of magic.
config.ebwizardry.tower_rarity=Tower Rarity
config.ebwizardry.ore_dimensions=Ore Dimensions
@@ -685,7 +700,7 @@ config.ebwizardry.show_summoned_creature_names=Show Summoned Creature Names
config.ebwizardry.friendly_fire=Friendly Fire
config.ebwizardry.telekinetic_disarmament=Telekinetic Disarmament
config.ebwizardry.discovery_mode=Discovery Mode
config.ebwizardry.enable_shift_scrolling=Enable Shift-_scrolling
config.ebwizardry.enable_shift_scrolling=Enable Shift-scrolling
config.ebwizardry.minion_revenge_targeting=Minion Revenge Targeting
config.ebwizardry.player_damage_scaling=Player Damage Scaling Factor
config.ebwizardry.npc_damage_scaling=NPC Damage Scaling Factor
@@ -697,6 +712,8 @@ config.ebwizardry.cast_command_name=Cast Spell Command Name
config.ebwizardry.discoverspell_command_name=Discover Spell Command Name
config.ebwizardry.ally_command_name=Set Ally Command Name
config.ebwizardry.allies_command_name=View Allies Command Name
config.ebwizardry.mind_control_targets_blacklist=Mind Control Targets Blacklist
config.ebwizardry.evil_wizard_dimensions=Evil Wizard Dimensions
config.ebwizardry.mobs_immune_to_fire=Mobs Immune To Fire
config.ebwizardry.mobs_immune_to_ice=Mobs Immune To Ice
@@ -717,25 +734,27 @@ config.ebwizardry.use_alternate_scroll_recipe.tooltip=Whether to require a magic
config.ebwizardry.teleport_through_unbreakable_blocks.tooltip=Whether players are allowed to teleport through unbreakable blocks (e.g. bedrock) using the phase step spell.
config.ebwizardry.show_summoned_creature_names.tooltip=Whether to show summoned creatures' names and owners above their heads.
config.ebwizardry.friendly_fire.tooltip=Whether to allow players to damage their designated allies using magic.
config.ebwizardry.telekinetic_disarmament.tooltip=Whether to allow players to disarm other players using the telekinesis spell.ebwizardry: Set to false to prevent stealing of items.
config.ebwizardry.telekinetic_disarmament.tooltip=Whether to allow players to disarm other players using the telekinesis spell. Set to false to prevent stealing of items.
config.ebwizardry.discovery_mode.tooltip=For those who like a sense of mystery! When set to true, spells you haven't cast yet will be unreadable until you cast them (on a per-world basis). Has no effect when in creative mode. Spells of identification will be unobtainable in survival mode if this is false.
config.ebwizardry.enable_shift_scrolling.tooltip=Whether you can switch between spells on a wand by scrolling with the mouse wheel while sneaking. Note that this will only affect you; other players connected to the same server obey their own settings.
config.ebwizardry.minion_revenge_targeting.tooltip=Whether summoned creatures can revenge attack their owner if their owner attacks them.
config.ebwizardry.player_damage_scaling.tooltip=Global damage scaling factor for the damage dealt by players casting spells, relative to 1.
config.ebwizardry.npc_damage_scaling.tooltip=Global damage scaling factor for the damage dealt by NPCs casting spells, relative to 1.
config.ebwizardry.cast_command_multiplier_limit.tooltip=Upper limit for the multipliers passed into the /cast command. This is here to stop players from accidentally breaking a world/server. Large blast mutipliers can cause extreme lag - you have been warned!
config.ebwizardry.summoned_creature_targets_whitelist.tooltip=List of names of entities which summoned creatures and wizards are allowed to attack, in addition to the defaults. Add mod creatures to this list if you want summoned creatures to attack them and they aren't already doing so. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry.wizard).
config.ebwizardry.summoned_creature_targets_blacklist.tooltip=List of names of entities which summoned creatures and wizards are specifically not allowed to attack, overriding the defaults and the whitelist. Add creatures to this list if allowing them to be attacked causes problems or is too destructive (removing creepers from this list is done at your own risk!). Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry.wizard).
config.ebwizardry.summoned_creature_targets_whitelist.tooltip=List of names of entities which summoned creatures and wizards are allowed to attack, in addition to the defaults. Add mod creatures to this list if you want summoned creatures to attack them and they aren't already doing so. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard).
config.ebwizardry.summoned_creature_targets_blacklist.tooltip=List of names of entities which summoned creatures and wizards are specifically not allowed to attack, overriding the defaults and the whitelist. Add creatures to this list if allowing them to be attacked causes problems or is too destructive (removing creepers from this list is done at your own risk!). Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard).
config.ebwizardry.spell_hud_position.tooltip=The position of the spell HUD.
config.ebwizardry.cast_command_name.tooltip=The name of the /cast command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /cast you would type /magic instead.
config.ebwizardry.discoverspell_command_name.tooltip=The name of the /discoverspell command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /discoverspell you would type /magic instead.
config.ebwizardry.ally_command_name.tooltip=The name of the /ally command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /ally you would type /magic instead.
config.ebwizardry.allies_command_name.tooltip=The name of the /allies command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /allies you would type /magic instead.
config.ebwizardry.mind_control_targets_blacklist.tooltip=List of names of entities which cannot be mind controlled, in addition to the defaults. Add creatures to this list if allowing them to be mind-controlled causes problems or could be exploited. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard).
config.ebwizardry.evil_wizard_dimensions.tooltip=List of dimension ids in which evil wizards can spawn.
config.ebwizardry.mobs_immune_to_fire.tooltip=List of names of entities that are immune to fire, in addition to the defaults. Add mod creatures to this list if you want them to be immune to fire magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry.wizard).
config.ebwizardry.mobs_immune_to_ice.tooltip=List of names of entities that are immune to ice, in addition to the defaults. Add mod creatures to this list if you want them to be immune to ice magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry.wizard).
config.ebwizardry.mobs_immune_to_lightning.tooltip=List of names of entities that are immune to lightning, in addition to the defaults. Add mod creatures to this list if you want them to be immune to lightning magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry.wizard).
config.ebwizardry.mobs_immune_to_wither.tooltip=List of names of entities that are immune to wither effects, in addition to the defaults. Add mod creatures to this list if you want them to be immune to withering magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry.wizard).
config.ebwizardry.mobs_immune_to_poison.tooltip=List of names of entities that are immune to poison, in addition to the defaults. Add mod creatures to this list if you want them to be immune to poison magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry.wizard).
config.ebwizardry.mobs_immune_to_fire.tooltip=List of names of entities that are immune to fire, in addition to the defaults. Add mod creatures to this list if you want them to be immune to fire magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard).
config.ebwizardry.mobs_immune_to_ice.tooltip=List of names of entities that are immune to ice, in addition to the defaults. Add mod creatures to this list if you want them to be immune to ice magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard).
config.ebwizardry.mobs_immune_to_lightning.tooltip=List of names of entities that are immune to lightning, in addition to the defaults. Add mod creatures to this list if you want them to be immune to lightning magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard).
config.ebwizardry.mobs_immune_to_wither.tooltip=List of names of entities that are immune to wither effects, in addition to the defaults. Add mod creatures to this list if you want them to be immune to withering magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard).
config.ebwizardry.mobs_immune_to_poison.tooltip=List of names of entities that are immune to poison, in addition to the defaults. Add mod creatures to this list if you want them to be immune to poison magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard).
wizard.debug=%1$s, %2$s, %3$s
@@ -655,20 +655,35 @@ commands.ebwizardry:discoverspell.removespell=Removed %1$s from %2$s's spell dis
config.ebwizardry.title.general=Mod Options
config.ebwizardry.category.spells=Configure Spells
config.ebwizardry.category.gameplay=Gameplay Settings
config.ebwizardry.category.gameplay.tooltip=Configure wizardry's general gameplay
config.ebwizardry.title.gameplay=Gameplay Settings
config.ebwizardry.subtitle.gameplay=Global settings that affect game mechanics.
config.ebwizardry.category.worldgen=World Generation Settings
config.ebwizardry.category.worldgen.tooltip=Configure wizardry's world generation features
config.ebwizardry.title.worldgen=World Generation Settings
config.ebwizardry.subtitle.worldgen=Settings that affect world generation.
config.ebwizardry.category.commands=Command Settings
config.ebwizardry.category.commands.tooltip=Configure wizardry's commands
config.ebwizardry.title.commands=Command Settings
config.ebwizardry.subtitle.commands=Settings for the commands added by Wizardry.
config.ebwizardry.category.client=Client Settings
config.ebwizardry.category.client.tooltip=Configure wizardry's display and controls
config.ebwizardry.title.client=Client Settings
config.ebwizardry.subtitle.client=Client-side settings that only affect the local minecraft game.
config.ebwizardry.category.spells=Spell Configuration
config.ebwizardry.category.spells.tooltip=Select which spells are enabled
config.ebwizardry.title.spells=Spell Configuration
config.ebwizardry.subtitle.spells=Set a spell to false to disable it.
config.ebwizardry.category.resistances=Configure Resistances
config.ebwizardry.category.resistances=Resistance Configuration
config.ebwizardry.category.resistances.tooltip=Configure which mobs are immune to different types of magic
config.ebwizardry.title.resistances=Resistance Configuration
config.ebwizardry.subtitle.resistances=See descriptions of individual options for more details.
config.ebwizardry.category.ids=Configure IDs
config.ebwizardry.category.ids.tooltip=Change the IDs used by wizardry
config.ebwizardry.title.ids=ID Configuration
config.ebwizardry.subtitle.ids=Change these IDs if they conflict with another mod.
config.ebwizardry.subtitle.resistances=Settings which allow entities to be made immune to certain types of magic.
config.ebwizardry.tower_rarity=Tower Rarity
config.ebwizardry.ore_dimensions=Ore Dimensions
@@ -685,7 +700,7 @@ config.ebwizardry.show_summoned_creature_names=Show Summoned Creature Names
config.ebwizardry.friendly_fire=Friendly Fire
config.ebwizardry.telekinetic_disarmament=Telekinetic Disarmament
config.ebwizardry.discovery_mode=Discovery Mode
config.ebwizardry.enable_shift_scrolling=Enable Shift-_scrolling
config.ebwizardry.enable_shift_scrolling=Enable Shift-scrolling
config.ebwizardry.minion_revenge_targeting=Minion Revenge Targeting
config.ebwizardry.player_damage_scaling=Player Damage Scaling Factor
config.ebwizardry.npc_damage_scaling=NPC Damage Scaling Factor
@@ -697,6 +712,8 @@ config.ebwizardry.cast_command_name=Cast Spell Command Name
config.ebwizardry.discoverspell_command_name=Discover Spell Command Name
config.ebwizardry.ally_command_name=Set Ally Command Name
config.ebwizardry.allies_command_name=View Allies Command Name
config.ebwizardry.mind_control_targets_blacklist=Mind Control Targets Blacklist
config.ebwizardry.evil_wizard_dimensions=Evil Wizard Dimensions
config.ebwizardry.mobs_immune_to_fire=Mobs Immune To Fire
config.ebwizardry.mobs_immune_to_ice=Mobs Immune To Ice
@@ -717,25 +734,27 @@ config.ebwizardry.use_alternate_scroll_recipe.tooltip=Whether to require a magic
config.ebwizardry.teleport_through_unbreakable_blocks.tooltip=Whether players are allowed to teleport through unbreakable blocks (e.g. bedrock) using the phase step spell.
config.ebwizardry.show_summoned_creature_names.tooltip=Whether to show summoned creatures' names and owners above their heads.
config.ebwizardry.friendly_fire.tooltip=Whether to allow players to damage their designated allies using magic.
config.ebwizardry.telekinetic_disarmament.tooltip=Whether to allow players to disarm other players using the telekinesis spell.ebwizardry: Set to false to prevent stealing of items.
config.ebwizardry.telekinetic_disarmament.tooltip=Whether to allow players to disarm other players using the telekinesis spell. Set to false to prevent stealing of items.
config.ebwizardry.discovery_mode.tooltip=For those who like a sense of mystery! When set to true, spells you haven't cast yet will be unreadable until you cast them (on a per-world basis). Has no effect when in creative mode. Spells of identification will be unobtainable in survival mode if this is false.
config.ebwizardry.enable_shift_scrolling.tooltip=Whether you can switch between spells on a wand by scrolling with the mouse wheel while sneaking. Note that this will only affect you; other players connected to the same server obey their own settings.
config.ebwizardry.minion_revenge_targeting.tooltip=Whether summoned creatures can revenge attack their owner if their owner attacks them.
config.ebwizardry.player_damage_scaling.tooltip=Global damage scaling factor for the damage dealt by players casting spells, relative to 1.
config.ebwizardry.npc_damage_scaling.tooltip=Global damage scaling factor for the damage dealt by NPCs casting spells, relative to 1.
config.ebwizardry.cast_command_multiplier_limit.tooltip=Upper limit for the multipliers passed into the /cast command. This is here to stop players from accidentally breaking a world/server. Large blast mutipliers can cause extreme lag - you have been warned!
config.ebwizardry.summoned_creature_targets_whitelist.tooltip=List of names of entities which summoned creatures and wizards are allowed to attack, in addition to the defaults. Add mod creatures to this list if you want summoned creatures to attack them and they aren't already doing so. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry.wizard).
config.ebwizardry.summoned_creature_targets_blacklist.tooltip=List of names of entities which summoned creatures and wizards are specifically not allowed to attack, overriding the defaults and the whitelist. Add creatures to this list if allowing them to be attacked causes problems or is too destructive (removing creepers from this list is done at your own risk!). Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry.wizard).
config.ebwizardry.summoned_creature_targets_whitelist.tooltip=List of names of entities which summoned creatures and wizards are allowed to attack, in addition to the defaults. Add mod creatures to this list if you want summoned creatures to attack them and they aren't already doing so. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard).
config.ebwizardry.summoned_creature_targets_blacklist.tooltip=List of names of entities which summoned creatures and wizards are specifically not allowed to attack, overriding the defaults and the whitelist. Add creatures to this list if allowing them to be attacked causes problems or is too destructive (removing creepers from this list is done at your own risk!). Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard).
config.ebwizardry.spell_hud_position.tooltip=The position of the spell HUD.
config.ebwizardry.cast_command_name.tooltip=The name of the /cast command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /cast you would type /magic instead.
config.ebwizardry.discoverspell_command_name.tooltip=The name of the /discoverspell command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /discoverspell you would type /magic instead.
config.ebwizardry.ally_command_name.tooltip=The name of the /ally command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /ally you would type /magic instead.
config.ebwizardry.allies_command_name.tooltip=The name of the /allies command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /allies you would type /magic instead.
config.ebwizardry.mind_control_targets_blacklist.tooltip=List of names of entities which cannot be mind controlled, in addition to the defaults. Add creatures to this list if allowing them to be mind-controlled causes problems or could be exploited. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard).
config.ebwizardry.evil_wizard_dimensions.tooltip=List of dimension ids in which evil wizards can spawn.
config.ebwizardry.mobs_immune_to_fire.tooltip=List of names of entities that are immune to fire, in addition to the defaults. Add mod creatures to this list if you want them to be immune to fire magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry.wizard).
config.ebwizardry.mobs_immune_to_ice.tooltip=List of names of entities that are immune to ice, in addition to the defaults. Add mod creatures to this list if you want them to be immune to ice magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry.wizard).
config.ebwizardry.mobs_immune_to_lightning.tooltip=List of names of entities that are immune to lightning, in addition to the defaults. Add mod creatures to this list if you want them to be immune to lightning magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry.wizard).
config.ebwizardry.mobs_immune_to_wither.tooltip=List of names of entities that are immune to wither effects, in addition to the defaults. Add mod creatures to this list if you want them to be immune to withering magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry.wizard).
config.ebwizardry.mobs_immune_to_poison.tooltip=List of names of entities that are immune to poison, in addition to the defaults. Add mod creatures to this list if you want them to be immune to poison magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry.wizard).
config.ebwizardry.mobs_immune_to_fire.tooltip=List of names of entities that are immune to fire, in addition to the defaults. Add mod creatures to this list if you want them to be immune to fire magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard).
config.ebwizardry.mobs_immune_to_ice.tooltip=List of names of entities that are immune to ice, in addition to the defaults. Add mod creatures to this list if you want them to be immune to ice magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard).
config.ebwizardry.mobs_immune_to_lightning.tooltip=List of names of entities that are immune to lightning, in addition to the defaults. Add mod creatures to this list if you want them to be immune to lightning magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard).
config.ebwizardry.mobs_immune_to_wither.tooltip=List of names of entities that are immune to wither effects, in addition to the defaults. Add mod creatures to this list if you want them to be immune to withering magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard).
config.ebwizardry.mobs_immune_to_poison.tooltip=List of names of entities that are immune to poison, in addition to the defaults. Add mod creatures to this list if you want them to be immune to poison magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. ebwizardry:wizard).
wizard.debug=%1$s, %2$s, %3$s
@@ -0,0 +1,741 @@
tile.ebwizardry:arcane_workbench.name=奥术工作台
tile.ebwizardry:crystal_ore.name=水晶矿
tile.ebwizardry:petrified_stone.name=石化石像
tile.ebwizardry:ice_statue.name=冰像
tile.ebwizardry:crystal_flower.name=水晶花
tile.ebwizardry:snare.name=陷阱
tile.ebwizardry:transportation_stone.name=传送石
tile.ebwizardry:spectral_block.name=幽冥块
tile.ebwizardry:crystal_block.name=水晶块
item.ebwizardry:magic_crystal.name=魔法水晶
item.ebwizardry:magic_wand.name=法杖
item.ebwizardry:apprentice_wand.name=学徒法杖
item.ebwizardry:advanced_wand.name=进阶法杖
item.ebwizardry:master_wand.name=大师法杖
item.ebwizardry:spell_book.name=法术书
item.ebwizardry:arcane_tome.name=奥法宝典
item.ebwizardry:arcane_tome.desc1=升级需求 %1$s
item.ebwizardry:arcane_tome.desc2=法杖升级至 %1$s 级别
item.ebwizardry:wizard_handbook.name=巫师手册
item.ebwizardry:wizard_handbook.desc=编写于 %1$s
item.ebwizardry:wand.buff=+%1$s %2$s 能力
item.ebwizardry:wand.spell=当前法术: %1$s
item.ebwizardry:wand.mana=魔力: %1$s/%2$s
item.ebwizardry:wand.addally=%1$s 已添加到你的盟友名单
item.ebwizardry:wand.removeally=%1$s 已移出你的盟友名单
item.ebwizardry:basic_fire_wand.name=余火法杖
item.ebwizardry:basic_ice_wand.name=寒霜法杖
item.ebwizardry:basic_lightning_wand.name=星火法杖
item.ebwizardry:basic_necromancy_wand.name=暗影法杖
item.ebwizardry:basic_earth_wand.name=森林法杖
item.ebwizardry:basic_sorcery_wand.name=神秘法杖
item.ebwizardry:basic_healing_wand.name=治愈法杖
item.ebwizardry:apprentice_fire_wand.name=学徒烈焰法杖
item.ebwizardry:apprentice_ice_wand.name=学徒冰霜法杖
item.ebwizardry:apprentice_lightning_wand.name=学徒风暴法杖
item.ebwizardry:apprentice_necromancy_wand.name=学徒死灵法杖
item.ebwizardry:apprentice_earth_wand.name=学徒大地法杖
item.ebwizardry:apprentice_sorcery_wand.name=学徒妖术法杖
item.ebwizardry:apprentice_healing_wand.name=学徒治愈法杖
item.ebwizardry:advanced_fire_wand.name=烈焰法杖
item.ebwizardry:advanced_ice_wand.name=冰霜法杖
item.ebwizardry:advanced_lightning_wand.name=风暴法杖
item.ebwizardry:advanced_necromancy_wand.name=死灵法杖
item.ebwizardry:advanced_earth_wand.name=大地法杖
item.ebwizardry:advanced_sorcery_wand.name=妖术法杖
item.ebwizardry:advanced_healing_wand.name=治愈法杖
item.ebwizardry:master_fire_wand.name=大师烈焰法杖
item.ebwizardry:master_ice_wand.name=大师冰霜法杖
item.ebwizardry:master_lightning_wand.name=大师风暴法杖
item.ebwizardry:master_necromancy_wand.name=大师死灵法杖
item.ebwizardry:master_earth_wand.name=大师大地法杖
item.ebwizardry:master_sorcery_wand.name=大师妖术法杖
item.ebwizardry:master_healing_wand.name=大师治愈法杖
item.ebwizardry:spectral_sword.name=幽冥剑
item.ebwizardry:spectral_pickaxe.name=幽冥镐
item.ebwizardry:spectral_bow.name=幽冥弓
item.ebwizardry:mana_flask.name=魔力瓶
item.ebwizardry:storage_upgrade.name=法杖存储升级
item.ebwizardry:siphon_upgrade.name=法杖汲取升级
item.ebwizardry:condenser_upgrade.name=法杖聚光升级
item.ebwizardry:range_upgrade.name=法杖范围升级
item.ebwizardry:duration_upgrade.name=法杖时限升级
item.ebwizardry:cooldown_upgrade.name=法杖冷却升级
item.ebwizardry:blast_upgrade.name=法杖爆破升级
item.ebwizardry:attunement_upgrade.name=法杖协调升级
item.ebwizardry:flaming_axe.name=炽烈之斧
item.ebwizardry:frost_axe.name=冰霜之斧
item.ebwizardry:firebomb.name=燃烧弹
item.ebwizardry:poison_bomb.name=毒液弹
item.ebwizardry:smoke_bomb.name=烟雾弹
item.ebwizardry:blank_scroll.name=空白卷轴
item.ebwizardry:scroll.name=卷轴 %1$s
item.ebwizardry:scroll.undiscovered.name=卷轴 "%1$s"
item.ebwizardry:identification_scroll.name=鉴定卷轴
item.ebwizardry:identification_scroll.desc1=%1$s 鉴定未知的
item.ebwizardry:identification_scroll.desc2=%1$s 法术书或卷轴
item.ebwizardry:identification_scroll.nothing_to_identify=没有可以鉴定的东西!
item.ebwizardry:armour_upgrade.name=奥术戳记:保护
item.ebwizardry:armour_upgrade.desc1=%1$s升级任何巫师护甲
item.ebwizardry:armour_upgrade.desc2=%1$s使其达到 %2$s传奇
item.ebwizardry:magic_silk.name=魔法丝绸
item.ebwizardry:wizard_armour.legendary=传奇
item.ebwizardry:wizard_armour.buff=-%1$s %2$s 消耗
item.ebwizardry:wizard_armour.mana=魔力: %1$s/%2$s
item.ebwizardry:wizard_hat.name=巫师帽
item.ebwizardry:wizard_robe.name=巫师法袍
item.ebwizardry:wizard_leggings.name=巫师护腿
item.ebwizardry:wizard_boots.name=巫师靴子
item.ebwizardry:wizard_hat_fire.name=烈焰法师帽子
item.ebwizardry:wizard_robe_fire.name=烈焰法师法袍
item.ebwizardry:wizard_leggings_fire.name=烈焰法师护腿
item.ebwizardry:wizard_boots_fire.name=烈焰法师靴子
item.ebwizardry:wizard_hat_ice.name=冰霜法师帽子
item.ebwizardry:wizard_robe_ice.name=冰霜法师法袍
item.ebwizardry:wizard_leggings_ice.name=冰霜法师护腿
item.ebwizardry:wizard_boots_ice.name=冰霜法师靴子
item.ebwizardry:wizard_hat_lightning.name=风暴法师帽子
item.ebwizardry:wizard_robe_lightning.name=风暴法师法袍
item.ebwizardry:wizard_leggings_lightning.name=风暴法师护腿
item.ebwizardry:wizard_boots_lightning.name=风暴法师靴子
item.ebwizardry:wizard_hat_necromancy.name=死灵法师帽子
item.ebwizardry:wizard_robe_necromancy.name=死灵法师法袍
item.ebwizardry:wizard_leggings_necromancy.name=死灵法师护腿
item.ebwizardry:wizard_boots_necromancy.name=死灵法师靴子
item.ebwizardry:wizard_hat_earth.name=大地法师帽子
item.ebwizardry:wizard_robe_earth.name=大地法师法袍
item.ebwizardry:wizard_leggings_earth.name=大地法师护腿
item.ebwizardry:wizard_boots_earth.name=大地法师靴子
item.ebwizardry:wizard_hat_sorcery.name=妖术法师帽子
item.ebwizardry:wizard_robe_sorcery.name=妖术法师法袍
item.ebwizardry:wizard_leggings_sorcery.name=妖术法师护腿
item.ebwizardry:wizard_boots_sorcery.name=妖术法师靴子
item.ebwizardry:wizard_hat_healing.name=治愈法师帽子
item.ebwizardry:wizard_robe_healing.name=治愈法师法袍
item.ebwizardry:wizard_leggings_healing.name=治愈法师护腿
item.ebwizardry:wizard_boots_healing.name=治愈法师靴子
item.ebwizardry:spawn_wizard.name=生成巫师
item.ebwizardry:spawn_evil_wizard.name=生成邪恶巫师
item.ebwizardry:spectral_helmet.name=幽冥头盔
item.ebwizardry:spectral_chestplate.name=幽冥胸甲
item.ebwizardry:spectral_leggings.name=幽冥护腿
item.ebwizardry:spectral_boots.name=幽冥靴子
entity.ebwizardry:summonedcreature.nameplate=%1$s 的 %2$s
entity.ebwizardry:summonedcreature.nameplate_fallback=某人的 %1$s
entity.ebwizardry:zombie_minion.name=僵尸
entity.ebwizardry:skeleton_minion.name=骷髅
entity.ebwizardry:spider_minion.name=蜘蛛
entity.ebwizardry:blaze_minion.name=烈焰人
entity.ebwizardry:wither_skeleton_minion.name=凋灵骷髅
entity.ebwizardry:ice_wraith.name=冰封幽灵
entity.ebwizardry:lightning_wraith.name=光明幽灵
entity.ebwizardry:shadow_wraith.name=阴影幽灵
entity.ebwizardry:spirit_wolf.name=精灵狼
entity.ebwizardry:spirit_horse.name=精灵马
entity.ebwizardry:ice_giant.name=冰封巨人
entity.ebwizardry:phoenix.name=凤凰
entity.ebwizardry:wizard.name=巫师
entity.ebwizardry:magic_slime.name=魔法史莱姆
entity.ebwizardry:silverfish_minion.name=蠹虫
entity.ebwizardry:storm_elemental.name=风暴元素
entity.ebwizardry:evil_wizard.name=巫师
entity.ebwizardry:decoy.name=诱饵
entity.ebwizardry:magic_missile.name=魔法
entity.ebwizardry:arc.name=魔法
entity.ebwizardry:spark_bomb.name=魔法
entity.ebwizardry:ice_shard.name=魔法
entity.ebwizardry:firebomb.name=魔法
entity.ebwizardry:poison_bomb.name=魔法
entity.ebwizardry:force_orb.name=魔法
entity.ebwizardry:spark.name=魔法
entity.ebwizardry:darkness_orb.name=魔法
entity.ebwizardry:fire_sigil.name=魔法
entity.ebwizardry:frost_sigil.name=魔法
entity.ebwizardry:lightning_sigil.name=魔法
entity.ebwizardry:lightning_arrow.name=魔法
entity.ebwizardry:firebolt.name=魔法
entity.ebwizardry:ice_charge.name=魔法
entity.ebwizardry:force_arrow.name=魔法
entity.ebwizardry:dart.name=魔法
entity.ebwizardry:lightning_disc.name=魔法
entity.ebwizardry:thunderbolt.name=魔法
entity.ebwizardry:decay.name=魔法
entity.ebwizardry:ice_lance.name=魔法
entity.ebwizardry:smoke_bomb.name=魔法
entity.ebwizardry:ice_spike.name=魔法
entity.ebwizardry:black_hole.name=黑洞
entity.ebwizardry:shield.name=盾
entity.ebwizardry:meteor.name=陨星
entity.ebwizardry:blizzard.name=暴风雪
entity.ebwizardry:bubble.name=气泡
entity.ebwizardry:tornado.name=飓风
entity.ebwizardry:lightning_hammer.name=雷神之锤
entity.ebwizardry:arrow_rain.name=箭雨
entity.ebwizardry:healing_aura.name=治疗灵气
entity.ebwizardry:forcefield.name=力场护盾
entity.ebwizardry:ring_of_fire.name=火环
entity.ebwizardry:earthquake.name=地震
entity.ebwizardry:falling_grass.name=落草
entity.ebwizardry:hailstorm.name=冰雹风暴
entity.ebwizardry:lightning_pulse.name=闪电脉冲
itemGroup.ebwizardry=巫术学
itemGroup.ebwizardryspells=卷轴
advancement.wizardry:root=新兴巫术
advancement.wizardry:root.desc=一个巫师掌握奥术的旅程
advancement.wizardry:crystal=一个奇异的水晶...
advancement.wizardry:crystal.desc=挖掘一个魔法水晶
advancement.wizardry:arcane_initiate=奥术启程
advancement.wizardry:arcane_initiate.desc=利用金锭,木棍和魔法水晶制造一根法杖
advancement.wizardry:apprentice=见习巫师
advancement.wizardry:apprentice.desc=使用奥法宝典来升级你的法杖
advancement.wizardry:master=大师级巫师
advancement.wizardry:master.desc=获得大师级法杖
advancement.wizardry:all_spells=巫师的自我修养
advancement.wizardry:all_spells.desc=在游戏中施放所有法术
advancement.wizardry:wizard_trade=魔法交易
advancement.wizardry:wizard_trade.desc=向巫师购买物品
advancement.wizardry:buy_master_spell=知识就是力量
advancement.wizardry:buy_master_spell.desc=向巫师购买一个大师级卷轴
advancement.wizardry:freeze_blaze=现在不太热了
advancement.wizardry:freeze_blaze.desc=把烈焰人冻成傻子
advancement.wizardry:charge_creep=它要炸了
advancement.wizardry:charge_creeper.desc='意外' 捕获爬行者
advancement.wizardry:frankenstein=弗兰肯斯坦
advancement.wizardry:frankenstein.desc=用闪电法术将猪变成僵尸猪人
advancement.wizardry:special_upgrade=奥术工匠
advancement.wizardry:special_upgrade.desc=对法杖进行特殊升级
advancement.wizardry:craft_flask=这是魔力,装瓶!
advancement.wizardry:craft_flask.desc=制作一个魔力瓶
advancement.wizardry:elemental=元素
advancement.wizardry:elemental.desc=获得元素法杖
advancement.wizardry:armour_set=现在你是一个正确的巫师
advancement.wizardry:armour_set.desc=制作并装备全套巫师护具
advancement.wizardry:legendary=传奇!
advancement.wizardry:legendary.desc=获得一件传奇级装备
advancement.wizardry:self_destruct=真是倒霉
advancement.wizardry:self_destruct.desc=被自己的魔法杀死
advancement.wizardry:pig_tornado=不会再次...
advancement.wizardry:pig_tornado.desc=骑着猪卷进飓风
advancement.wizardry:jam_wizard=扰乱会议
advancement.wizardry:jam_wizard.desc=对一个巫师使用奥术干扰
advancement.wizardry:slime_skeleton=棘手局面
advancement.wizardry:slime_skeleton.desc=利用史莱姆吞噬骷髅
advancement.wizardry:anger_wizard=你会后悔的
advancement.wizardry:anger_wizard.desc=使一个巫师发怒
advancement.wizardry:defeat_evil_wizard=正义降临
advancement.wizardry:defeat_evil_wizard.desc=击败邪恶巫师
advancement.wizardry:max_out_wand=整装上阵
advancement.wizardry:max_out_wand.desc=将大师级法杖升级到最强
advancement.wizardry:element_master=元素掌控
advancement.wizardry:element_master.desc=施放任何元素的法术
advancement.wizardry:identify_spell=奥术鉴定
advancement.wizardry:identify_spell.desc=使用鉴定卷轴来鉴定法术书或卷轴
tile.ebwizardry:transportation_stone.confirm=施展法术时你将会回到这里 %1$s
tile.ebwizardry:transportation_stone.invalid=你必须先将八个传送石围成圆圈!
container.ebwizardry:arcane_workbench=奥术工作台
container.ebwizardry:arcane_workbench.apply=应用
container.ebwizardry:arcane_workbench.mana=魔力:
container.ebwizardry:arcane_workbench.upgrades=应用升级:
tier.basic=新手
tier.apprentice=学徒
tier.advanced=进阶
tier.master=大师
element.simple=无
element.fire=火
element.ice=冰
element.lightning=闪电
element.necromancy=死灵
element.earth=大地
element.sorcery=妖术
element.healing=治愈
element.simple.wizard=巫师
element.fire.wizard=烈焰法师
element.ice.wizard=冰霜法师
element.lightning.wizard=风暴法师
element.necromancy.wizard=死灵法师
element.earth.wizard=大地法师
element.sorcery.wizard=妖术法师
element.healing.wizard=治愈法师
spelltype.attack=攻击
spelltype.defence=防御
spelltype.utility=实用
spelltype.minion=仆从
spell.disabled=%1$s 已在配置文件中禁用
spell.resist=%1$s 排斥 %2$s
spell.discover=发现了这个法术 %1$s
spell.ebwizardry:agility=敏捷
spell.ebwizardry:arc=电弧
spell.ebwizardry:arcane_jammer=奥术干扰
spell.ebwizardry:arrow_rain=箭雨
spell.ebwizardry:banish=驱逐
spell.ebwizardry:black_hole=黑洞
spell.ebwizardry:blink=闪现
spell.ebwizardry:blizzard=暴雪
spell.ebwizardry:bubble=气泡
spell.ebwizardry:chain_lightning=闪电链条
spell.ebwizardry:clairvoyance=千里眼
spell.ebwizardry:cobwebs=结网
spell.ebwizardry:conjure_armour=唤魔护甲
spell.ebwizardry:conjure_bow=唤魔弓
spell.ebwizardry:conjure_pickaxe=唤魔镐子
spell.ebwizardry:conjure_sword=唤魔剑
spell.ebwizardry:cure_effects=治愈效应
spell.ebwizardry:curse_of_soulbinding=灵魂绑定
spell.ebwizardry:darkness_orb=黑暗宝珠
spell.ebwizardry:darkvision=黑暗视觉
spell.ebwizardry:dart=飞镖
spell.ebwizardry:decay=腐化
spell.ebwizardry:decoy=诱饵
spell.ebwizardry:detonate=引爆
spell.ebwizardry:diamondflesh=金刚不坏
spell.ebwizardry:earthquake=地震
spell.ebwizardry:entrapment=诱捕
spell.ebwizardry:fireball=火球
spell.ebwizardry:firebolt=火箭
spell.ebwizardry:firebomb=火焰弹
spell.ebwizardry:fire_resistance=防火
spell.ebwizardry:fire_sigil=火之印记
spell.ebwizardry:fireskin=火焰之肤
spell.ebwizardry:firestorm=火焰风暴
spell.ebwizardry:flame_ray=火焰射线
spell.ebwizardry:flaming_axe=赤炎之斧
spell.ebwizardry:flaming_weapon=赤炎武器
spell.ebwizardry:flight=飞行
spell.ebwizardry:font_of_mana=魔力字符
spell.ebwizardry:font_of_vitality=活力字符
spell.ebwizardry:force_arrow=力量箭矢
spell.ebwizardry:forcefield=力场护盾
spell.ebwizardry:force_orb=力场宝珠
spell.ebwizardry:forests_curse=森林诅咒
spell.ebwizardry:freeze=冻结
spell.ebwizardry:freezing_weapon=冻结武器
spell.ebwizardry:frost_axe=寒霜斧
spell.ebwizardry:frost_ray=寒霜射线
spell.ebwizardry:frost_sigil=寒霜印记
spell.ebwizardry:glide=滑翔
spell.ebwizardry:greater_fireball=大型火球
spell.ebwizardry:greater_heal=强效治疗
spell.ebwizardry:group_heal=团体治疗
spell.ebwizardry:growth_aura=生长光环
spell.ebwizardry:hailstorm=冰雹风暴
spell.ebwizardry:heal=治愈
spell.ebwizardry:heal_ally=友军治愈
spell.ebwizardry:healing_aura=治愈灵气
spell.ebwizardry:homing_spark=跟踪闪电
spell.ebwizardry:ice_age=冰霜纪元
spell.ebwizardry:ice_charge=冰霜冲击
spell.ebwizardry:ice_lance=冰霜刺枪
spell.ebwizardry:ice_shard=冰霜碎片
spell.ebwizardry:ice_shroud=冰霜护体
spell.ebwizardry:ice_spikes=冰霜尖刺
spell.ebwizardry:ice_statue=冰雕
spell.ebwizardry:ignite=点燃
spell.ebwizardry:imbue_weapon=武器同调
spell.ebwizardry:intimidate=恐吓
spell.ebwizardry:invigorating_presence=振奋
spell.ebwizardry:invisibility=隐形
spell.ebwizardry:invoke_weather=祈雨
spell.ebwizardry:ironflesh=钢筋铁骨
spell.ebwizardry:leap=跳跃
spell.ebwizardry:levitation=漂浮
spell.ebwizardry:life_drain=生命汲取
spell.ebwizardry:light=光芒
spell.ebwizardry:lightning_arrow=闪电箭矢
spell.ebwizardry:lightning_bolt=闪电弩箭
spell.ebwizardry:lightning_disc=闪电轮盘
spell.ebwizardry:lightning_hammer=雷神之锤
spell.ebwizardry:lightning_pulse=闪电脉冲
spell.ebwizardry:lightning_ray=闪电射线
spell.ebwizardry:lightning_sigil=闪电印记
spell.ebwizardry:lightning_web=电网
spell.ebwizardry:magic_missile=魔法飞弹
spell.ebwizardry:metamorphosis=拟态
spell.ebwizardry:meteor=陨星
spell.ebwizardry:mind_control=心灵控制
spell.ebwizardry:mind_trick=心灵欺诈
spell.ebwizardry:none=[空槽]
spell.ebwizardry:oakflesh=苍劲如松
spell.ebwizardry:petrify=石化
spell.ebwizardry:phase_step=相位跳跃
spell.ebwizardry:plague_of_darkness=黑暗瘟疫
spell.ebwizardry:pocket_furnace=口袋熔炉
spell.ebwizardry:pocket_workbench=口袋工作台
spell.ebwizardry:poison=毒液
spell.ebwizardry:poison_bomb=毒液弹
spell.ebwizardry:replenish_hunger=回复饥饿
spell.ebwizardry:ring_of_fire=火环
spell.ebwizardry:shadow_ward=阴影护盾
spell.ebwizardry:shield=护盾
spell.ebwizardry:shockwave=冲击波
spell.ebwizardry:silverfish_swarm=蠹虫群
spell.ebwizardry:sixth_sense=第六感
spell.ebwizardry:slime=史莱姆
spell.ebwizardry:smoke_bomb=烟雾弹
spell.ebwizardry:snare=陷阱
spell.ebwizardry:snowball=雪球
spell.ebwizardry:spark_bomb=电击弹
spell.ebwizardry:spectral_pathway=幽径
spell.ebwizardry:spider_swarm=蜘蛛群
spell.ebwizardry:static_aura=静态灵气
spell.ebwizardry:summon_blaze=召唤烈焰人
spell.ebwizardry:summon_ice_giant=召唤冰封巨人
spell.ebwizardry:summon_ice_wraith=召唤冰封幽灵
spell.ebwizardry:summon_iron_golem=召唤铁傀儡
spell.ebwizardry:summon_lightning_wraith=召唤闪电幽灵
spell.ebwizardry:summon_phoenix=召唤凤凰
spell.ebwizardry:summon_shadow_wraith=召唤阴影幽灵
spell.ebwizardry:summon_skeleton=召唤骷髅
spell.ebwizardry:summon_skeleton_legion=召唤骷髅军团
spell.ebwizardry:summon_snow_golem=召唤雪傀儡
spell.ebwizardry:summon_spirit_horse=召唤幽灵马
spell.ebwizardry:summon_spirit_wolf=召唤幽灵狼
spell.ebwizardry:summon_storm_elemental=召唤风暴元素
spell.ebwizardry:summon_wither_skeleton=召唤凋灵骷髅
spell.ebwizardry:summon_zombie=召唤僵尸
spell.ebwizardry:telekinesis=隔空取物
spell.ebwizardry:thunderbolt=雷电
spell.ebwizardry:thunderstorm=雷暴
spell.ebwizardry:tornado=飓风
spell.ebwizardry:transience=金身
spell.ebwizardry:transportation=传送
spell.ebwizardry:vanishing_box=幻灭之盒
spell.ebwizardry:wall_of_frost=冰霜之墙
spell.ebwizardry:water_breathing=水下呼吸
spell.ebwizardry:whirlwind=旋风
spell.ebwizardry:wither=凋零
spell.ebwizardry:wither_skull=凋灵头颅
spell.ebwizardry:agility.desc=为施法者提供更快的移速和更高的跳跃高度,持续时间30秒。
spell.ebwizardry:arc.desc=向目标发射闪电,
spell.ebwizardry:arcane_jammer.desc=阻止目标15秒使用魔法。
spell.ebwizardry:arrow_rain.desc=“弓箭手,射击!”
spell.ebwizardry:banish.desc=强制目标传送到某一范围内的随机位置。
spell.ebwizardry:black_hole.desc=撕裂现实。
spell.ebwizardry:blink.desc=将施法者远距离传送至其指向的地方。
spell.ebwizardry:blizzard.desc=创建一个旋转的冰封地带,减缓并持续伤害困在里面的任何东西。施法者免受伤害,但仍然受到减速影响。
spell.ebwizardry:bubble.desc=射出一股气泡,击中的目标会无助地向上漂浮。目标将在一段时间后坠落并且受到伤害。
spell.ebwizardry:chain_lightning.desc=向目标发射闪电,能够向额外目标跳跃至多两次。
spell.ebwizardry:clairvoyance.desc=创建一条通向被记录的的坐标的道路。选择此法术后,潜行右键来点击一个方块设置坐标,通常施展此法术来创建道路。该道路将在90秒后消失。
spell.ebwizardry:cobwebs.desc=在你指向的地方生成蜘蛛网,极大减慢被困住的生物的移动速度,如果未被破坏,蛛网将在20秒后消失。
spell.ebwizardry:conjure_armour.desc=在施法者身上制造幽冥护甲,与铁护甲等效。护甲持续60秒,施法者必须要有一个空装备槽。
spell.ebwizardry:conjure_bow.desc=创建一个无限箭矢的幽冥弓,持续时间30秒。
spell.ebwizardry:conjure_pickaxe.desc=创建一个与铁镐等效的幽冥镐,持续时间30秒。
spell.ebwizardry:conjure_sword.desc=创建一把与铁剑等效的幽冥剑,持续时间30秒。
spell.ebwizardry:cure_effects.desc=移除施法者目前的任何药水效果,不论好坏。
spell.ebwizardry:curse_of_soulbinding.desc=使目标的灵魂与施法者的灵魂绑定,意味施法者受到的伤害会转移给受害者,直到受害者或者施法者死亡。
spell.ebwizardry:darkness_orb.desc=向你指的方向发射一到移动缓慢的黑暗能量,无论击中什么,其都会凋零。
spell.ebwizardry:darkvision.desc=给予施法者夜视45秒。
spell.ebwizardry:dart.desc=向你指的方向发射飞镖,伤害并削弱目标。
spell.ebwizardry:decay.desc=在地表制造腐化,任何生物接触都会受到感染,随着时间流逝而持续造成伤害,并且受害者行走过的地面会蔓延更多的腐化。
spell.ebwizardry:decoy.desc=创建一个虚假的施法者克隆体,用来吸引怪物仇恨,30秒后诱饵消失。
spell.ebwizardry:detonate.desc=在你指向的地方发生爆炸,如果附近有生物或者施法者距离太近,也会受到伤害。
spell.ebwizardry:diamondflesh.desc=“你的箭矢就是在挠痒痒!”
spell.ebwizardry:earthquake.desc=一个真正的大地大法师可以令沧海化为桑田。
spell.ebwizardry:entrapment.desc=将目标陷入黑暗,其将被无助地向上牵引而且不断地受到伤害。
spell.ebwizardry:fireball.desc=朝你指的方向发射一个火球。
spell.ebwizardry:firebolt.desc=向你面前一小段距离喷射火焰。
spell.ebwizardry:firebomb.desc=在你指的方向投掷一个燃烧瓶,在撞击时爆炸并让目标着火。
spell.ebwizardry:fire_resistance.desc=施法者防火30秒。
spell.ebwizardry:fire_sigil.desc=在地上放置一个魔法火焰陷阱,它会伤害并点燃触发它的生物。
spell.ebwizardry:fireskin.desc=将施法者笼罩在火焰中30秒,任何攻击都会使攻击者自燃。
spell.ebwizardry:firestorm.desc=“吾乃巨龙。”
spell.ebwizardry:flame_ray.desc=在你指的方向产生一股火焰,它会持续点燃并伤害目标。
spell.ebwizardry:flaming_axe.desc=制造一把燃烧的斧头,击中敌人会使其着火,持续时间30秒。
spell.ebwizardry:flaming_weapon.desc=暂时性地将火焰的力量附加在快捷栏的第一件武器上,武器能使受害者着火,法术在45秒后失效。
spell.ebwizardry:flight.desc=像鹰一样翱翔。
spell.ebwizardry:font_of_mana.desc=“我们充满了强大的魔法能量,它似乎是来自...”-摘自一位被遗忘的法师的日志中,该页面的其余部分已经被烧毁。
spell.ebwizardry:font_of_vitality.desc=令人惊讶的感觉。
spell.ebwizardry:force_arrow.desc=在你指向的地方射出一根强有力的箭矢。
spell.ebwizardry:forcefield.desc=在你的周围生成一个能够排斥生物和偏移弹射物的力场。
spell.ebwizardry:force_orb.desc=发射一个力场,在受到撞击时会伤害并排斥附近的生物。
spell.ebwizardry:forests_curse.desc=“你胆敢进入我的森林!”
spell.ebwizardry:freeze.desc=冰冻目标10秒,也能把水冻结和在地表造雪。
spell.ebwizardry:freezing_weapon.desc=暂时性地将冰霜的力量附加在快捷栏的第一件武器上,武器能使受害者冻伤,法术在45秒后失效。
spell.ebwizardry:frost_axe.desc=制造一把冰霜之斧,击中敌人时将其冻伤,持续时间30秒。
spell.ebwizardry:frost_ray.desc=在你指向的地方制造一股霜冻流,可将目标减慢并持续伤害。
spell.ebwizardry:frost_sigil.desc=在地表放置一个魔法冰封陷阱,触发陷阱的生物会被冻结并受到伤害。
spell.ebwizardry:glide.desc=允许施法者在空中按住使用按钮向下滑行。
spell.ebwizardry:greater_fireball.desc=在你指向的方向发射一个大火球,在受到碰撞时发生爆炸。
spell.ebwizardry:greater_heal.desc=治疗施法者四颗心。
spell.ebwizardry:group_heal.desc=治疗施法者、附近的盟友和召唤生物三颗心。
spell.ebwizardry:growth_aura.desc=加速施法者附近作物的生长,还能在草地上长杂草和花朵。
spell.ebwizardry:hailstorm.desc=正是在第三纪元的凛冬,冰霜法师发现了他们真正的力量。
spell.ebwizardry:heal.desc=治疗施法者两颗心。
spell.ebwizardry:heal_ally.desc=治疗目标两颗半心。
spell.ebwizardry:healing_aura.desc=创建一个治疗能量力场,可以治疗内部的任何盟友。治疗力场内任何不死属性的生物都会受到伤害。
spell.ebwizardry:homing_spark.desc=制造一个向敌人移动的浮游火花。
spell.ebwizardry:ice_age.desc=“你将永远被冰封于此!”
spell.ebwizardry:ice_charge.desc=发射一个冰块,撞击时发生爆裂并冻伤附近的生物并向各个方向发射碎片。
spell.ebwizardry:ice_lance.desc=向你指的方向发射一支巨大能够穿透目标的冰矛,在此过程中能够伤害并且冻伤目标。
spell.ebwizardry:ice_shard.desc=在你指向的方向发射一个冰碎片,在命中目标时会使目标受到伤害并减缓速度。
spell.ebwizardry:ice_shroud.desc=在施法者身上产生一股寒气并持续三十秒,任何攻击者都会遭到冻伤。
spell.ebwizardry:ice_spikes.desc=锋利的冰刺从你指向的地面升起,刺穿上面的任何生物。
spell.ebwizardry:ice_statue.desc=将目标冻住20秒直到其打破束缚,目标被冻结时不能移动或者做任何事情,也不会受到伤害。
spell.ebwizardry:ignite.desc=将目标点燃十秒,也能像打火石一样工作。
spell.ebwizardry:imbue_weapon.desc=将魔力浸染在施法者快捷栏的第一个武器上,使其更加实用,法术在45秒后失效。
spell.ebwizardry:intimidate.desc=发出可怕的咆哮声,附近的生物会在恐惧中逃离。惊恐的生物会在30秒后恢复正常。
spell.ebwizardry:invigorating_presence.desc=使施法者和附近的盟友增加攻击力,持续45秒。
spell.ebwizardry:invisibility.desc=使施法者隐形30秒。
spell.ebwizardry:invoke_weather.desc=改变天气。
spell.ebwizardry:ironflesh.desc=极大地提升施法者的抗性,持续30秒。
spell.ebwizardry:leap.desc=使施法者向上跳跃几个方块并稍微向前移动。
spell.ebwizardry:levitation.desc=按住使用物品按键可以向上飘起。在落地前使用可以免除掉落伤害。
spell.ebwizardry:life_drain.desc=在你指向的方向发射一股凋零的能量,它能吸收目标的生命来补充你的生命。
spell.ebwizardry:light.desc=创造一簇魔法光芒照亮附近的区域,持续时间30秒。
spell.ebwizardry:lightning_arrow.desc=在你指向的方向发射一道闪电。
spell.ebwizardry:lightning_bolt.desc=使闪电击中你指向的地方。
spell.ebwizardry:lightning_disc.desc=在你指向的方向发射一个闪电轮,并搜寻目标。
spell.ebwizardry:lightning_hammer.desc=“以神之愤怒惩戒你!”
spell.ebwizardry:lightning_pulse.desc=使施法者附近的地面充能,伤害和排斥附近的生物。
spell.ebwizardry:lightning_ray.desc=在你指向的方向制造一股闪电,可以不断地伤害目标。
spell.ebwizardry:lightning_sigil.desc=在地上放置一个魔法闪电陷阱,它会对触发它的生物造成伤害并产生闪电链打击附近的生物。
spell.ebwizardry:lightning_web.desc=“专注,将你脑海中的风暴通过法杖引导出来,释放它的愤怒。”
spell.ebwizardry:magic_missile.desc=在你指向的方向发射一道魔法飞弹。
spell.ebwizardry:metamorphosis.desc=将目标变成另一种形态,只适用与某些生物。
spell.ebwizardry:meteor.desc=一些巫师只是想看到世界在燃烧...
spell.ebwizardry:mind_control.desc=心灵控制目标持续30秒,被控制方会为施法者而战。对于意志强大的生物无效。(心灵终结仪了解下)
spell.ebwizardry:mind_trick.desc=使目标迷惑15秒,其无法进行攻击。如果目标受到伤害,效果会被消除。
spell.ebwizardry:none.desc=要使用/give命令获取法术书,请使用元数据 /give [player] ebwizardry:spell_book 1 [spell id](如果你发现这本书出现在箱子里,那么说明某些mod将其打乱了)
spell.ebwizardry:oakflesh.desc=施法者抗性提升30秒。
spell.ebwizardry:petrify.desc=将目标变成石头,直到其打破束缚,束缚在黑暗中有几率会被打破。目标被石化后不能移动或者做任何事情,但也不会受到伤害。
spell.ebwizardry:phase_step.desc=传送施法者通过一个方块厚的墙面。范围升级会增加你的传送厚度。
spell.ebwizardry:plague_of_darkness.desc=黑暗将把他们全部消灭...
spell.ebwizardry:pocket_furnace.desc=在施法者的背包里熔炼多达五个物品。快捷栏的物品会被优先熔炼。
spell.ebwizardry:pocket_workbench.desc=允许施法者制作物品,就像在工作台上制作一样。
spell.ebwizardry:poison.desc=在你指向的方向发射毒液。
spell.ebwizardry:poison_bomb.desc=在你指向的方向发射一枚毒液弹,撞击后爆炸并且毒害附近的生物。
spell.ebwizardry:replenish_hunger.desc=补充施法者六格饥饿值。
spell.ebwizardry:ring_of_fire.desc=在施法者周围制造一个火圈,对周围的敌人造成伤害并将其点燃。
spell.ebwizardry:shadow_ward.desc=在施法者面前制造一堵暗黑墙,所受到伤害的一半都会返回到攻击者身上。
spell.ebwizardry:shield.desc=制造一个能够阻挡弹射物和魔法的力场屏障。同时也会使施法者得到虚弱的效果。
spell.ebwizardry:shockwave.desc=Boom.
spell.ebwizardry:silverfish_swarm.desc="Ahhhh! 他们正在增加!"
spell.ebwizardry:sixth_sense.desc=使施法者能够感知到附近的生物的位置,甚至能够透过墙壁,持续20秒。
spell.ebwizardry:slime.desc=用史莱姆吞噬目标,减缓目标速度并对其造成伤害。史莱姆在10秒后破裂。
spell.ebwizardry:smoke_bomb.desc=在你指向的方向发射一个烟雾弹,能够在短时间内释放出烟雾并且使附近的生物致盲。
spell.ebwizardry:snare.desc=在地面放置一个陷阱,触发陷阱的生物会被减缓速度并且受到伤害。
spell.ebwizardry:snowball.desc=在你指向的方向发射一个雪球。
spell.ebwizardry:spark_bomb.desc=在你指向的方向发射一个电击弹,附近的敌人会受到电击。
spell.ebwizardry:spectral_pathway.desc=在你面前制造一个不可破坏的魔法桥梁,能够延伸15个方块,桥会在60秒后消失。
spell.ebwizardry:spider_swarm.desc=召唤一群毒蜘蛛为你战斗,如果毒蜘蛛没有被杀死会在30秒后消失。
spell.ebwizardry:static_aura.desc=用闪电将施法者包围,持续30秒,任何攻击都会使攻击者遭到电击。
spell.ebwizardry:summon_blaze.desc=召唤一个烈焰人为你战斗,如果烈焰人没有被杀死会在30秒后消失。
spell.ebwizardry:summon_ice_giant.desc=“粉碎他们!”
spell.ebwizardry:summon_ice_wraith.desc=召唤一个冰封幽灵为你战斗,如果冰封幽灵没有被杀死会在30秒后消失。
spell.ebwizardry:summon_iron_golem.desc=Automatic automated autonomous automaton.
spell.ebwizardry:summon_lightning_wraith.desc=召唤一个闪电幽灵为你战斗,如果闪电幽灵没有被杀死会在30秒后消失。
spell.ebwizardry:summon_phoenix.desc=自灰烬中重生...
spell.ebwizardry:summon_shadow_wraith.desc=召唤一个阴影幽灵为你战斗。
spell.ebwizardry:summon_skeleton.desc=召唤一个骷髅为你战斗,如果骷髅没有被杀死会在30秒后消失。
spell.ebwizardry:summon_skeleton_legion.desc=“复活吧,不死军!”
spell.ebwizardry:summon_snow_golem.desc=召唤一个雪傀儡为你战斗。一直持续到雪傀儡死亡为止。
spell.ebwizardry:summon_spirit_horse.desc=召唤一匹幽灵马让你乘骑。在下马后幽灵马会消失,你可以用法杖右键来遣散它。
spell.ebwizardry:summon_spirit_wolf.desc=召唤一匹幽灵狼为你战斗。幽灵狼只有在被杀死的时候会消失,你可以用法杖右键来遣散它。
spell.ebwizardry:summon_storm_elemental.desc=“风暴元素:古老的元素的显现,它难以抑制其中的原始力量。” -巫师手册奥术生物章,卷 I_i
spell.ebwizardry:summon_wither_skeleton.desc=召唤一个凋灵骷髅为你战斗,凋灵骷髅会在消亡后消失。
spell.ebwizardry:summon_zombie.desc=召唤一个僵尸为你战斗,如果僵尸没有被杀死会在30秒后消失。
spell.ebwizardry:telekinesis.desc=移动一个掉落物或其他小物体到你面前,或者远程打开你指向的方块(相当于右击),也可以用来取下玩家的装备。
spell.ebwizardry:thunderbolt.desc=发射一道雷击震退目标
spell.ebwizardry:thunderstorm.desc="Mwahahahahahaha!"
spell.ebwizardry:tornado.desc=在你指向的方向释放一个飓风,在飓风路径上的任何东西都会被抛上天。
spell.ebwizardry:transience.desc=使施法者金身20秒,施法者可以免疫所有伤害,但是不能破坏或者放置方块也不能造成任何伤害。
spell.ebwizardry:transportation.desc=将施法者传送到已记录的石圈。想要使用此法术,需要制造一个传送石圈,然后用法杖右击。
spell.ebwizardry:vanishing_box.desc=允许施法者访问末影箱子。
spell.ebwizardry:wall_of_frost.desc=寒冬萦绕于指尖。
spell.ebwizardry:water_breathing.desc=允许施法者水下呼吸60秒。
spell.ebwizardry:whirlwind.desc=使目标被吹起并快速远离你。
spell.ebwizardry:wither.desc=发射一股暗黑射线,任何与其接触的东西都将凋零。
spell.ebwizardry:wither_skull.desc=在你指向的方向发射一个凋灵头颅。
spell.ebwizardry:invoke_weather.sun=雨渐渐停止...
spell.ebwizardry:invoke_weather.rain=天堂开启了...
spell.ebwizardry:transportation.missing=你的记录石圈遗失或是被阻挡...
spell.ebwizardry:transportation.undefined=你必须先记录一个石圈的位置!
spell.ebwizardry:transportation.wrongdimension=你的记录石圈在另一个维度里....
spell.ebwizardry:clairvoyance.searching=搜寻中...
spell.ebwizardry:clairvoyance.confirm=投掷在路径 %1$s 现在返回到这一个点
spell.ebwizardry:clairvoyance.outofrange=你记录坐标太远或者无法访问
spell.ebwizardry:clairvoyance.undefined=你必须首先记录一个坐标!
spell.ebwizardry:clairvoyance.wrongdimension=你的记录坐标在另一个维度里....
potion.ebwizardry:frost=冻伤
potion.ebwizardry:fireskin=火焰之肤
potion.ebwizardry:ice_shroud=冰霜护体
potion.ebwizardry:static_aura=静态灵气
potion.ebwizardry:transience=金身
potion.ebwizardry:decay=腐化
potion.ebwizardry:sixth_sense=第六感
potion.ebwizardry:arcane_jammer=奥术干扰
potion.ebwizardry:mind_trick=心灵欺诈
potion.ebwizardry:mind_control=心灵控制
potion.ebwizardry:font_of_mana=魔力字符
potion.ebwizardry:fear=恐惧
enchantment.ebwizardry:magic_sword=灌注
enchantment.ebwizardry:magic_bow=灌注
enchantment.ebwizardry:flaming_weapon=火焰灌注
enchantment.ebwizardry:freezing_weapon=冰霜灌注
key.categories.ebwizardry=巫术学
key.ebwizardry.next_spell=下一个法术
key.ebwizardry.previous_spell=上一个法术
death.attack.wizardry_magic=%1$s 被 %2$s 使用魔法杀死
death.attack.indirect_wizardry_magic=%1$s 被 %2$s 使用魔法杀死
commands.ebwizardry:cast.usage=/%1$s <法术> [玩家] [伤害倍数] [范围倍数] [时限倍数] [爆炸倍数]
commands.ebwizardry:cast.success=成功发动 %1$s
commands.ebwizardry:cast.success_continuous=成功发动 %1$s ;重复该条指令停止
commands.ebwizardry:cast.success_remote=成功发动 %1$s 至 %2$s
commands.ebwizardry:cast.success_remote_continuous=成功发动 %1$s 至 %2$s ;重复该条指令停止
commands.ebwizardry:cast.fail=无法 %1$s
commands.ebwizardry:cast.not_found==没有 %1$s 这种法术ID
commands.ebwizardry:cast.tag_error=数据标签解析错误: %s
commands.ebwizardry:ally.usage=/%1$s <玩家> [玩家]
commands.ebwizardry:ally.addally=%1$s 已添加到 %2$s 的盟友列表
commands.ebwizardry:ally.removeally=%1$s 已经从 %2$s 的盟友列表中移除
commands.ebwizardry:ally.self=玩家不能成为自己的盟友!
commands.ebwizardry:ally.permission=你没有权限改变其它玩家的盟友
commands.ebwizardry:allies.usage=/%1$s [玩家]
commands.ebwizardry:allies.list=与你结盟的玩家 %1$s
commands.ebwizardry:allies.list_other=玩家结盟 %1$s: %2$s
commands.ebwizardry:allies.permission=你没有权限查看其它玩家的盟友
commands.ebwizardry:allies.none=无
commands.ebwizardry:discoverspell.usage=/%1$s <法术/所有/清除> [玩家]
commands.ebwizardry:discoverspell.not_found=没有 %1$s 这种法术ID
commands.ebwizardry:discoverspell.clear=从 %1$s 中清除所有法术探索数据
commands.ebwizardry:discoverspell.all=添加所有的法术到 %1$s 的法术探索数据中
commands.ebwizardry:discoverspell.addspell=将 %1$s 添加 %2$s 的法术探索数据中
commands.ebwizardry:discoverspell.removespell=将 %1$s 从 %2$s 的法术探索数据中移除
config.ebwizardry.title.general=Mod 配置
config.ebwizardry.category.spells=配置法术
config.ebwizardry.category.spells.tooltip=选择以启用法术
config.ebwizardry.title.spells=法术配置
config.ebwizardry.subtitle.spells=将一个法术设置为false以禁用。
config.ebwizardry.category.resistances=配置抗性
config.ebwizardry.category.resistances.tooltip=配置某些怪物对不同属性魔法的抗性
config.ebwizardry.title.resistances=抗性配置
config.ebwizardry.subtitle.resistances=详情请参考个别选项说明。
config.ebwizardry.category.ids=配置 IDs
config.ebwizardry.category.ids.tooltip=改变巫师的ID
config.ebwizardry.title.ids=ID 配置
config.ebwizardry.subtitle.ids=如果这些ID与另一个Mod发生冲突,请更改这些ID
config.ebwizardry.tower_rarity=巫师塔稀有程度
config.ebwizardry.ore_dimensions=水晶矿生成维度
config.ebwizardry.flower_dimensions=水晶花生成维度
config.ebwizardry.tower_dimensions=巫师塔生成维度
config.ebwizardry.spell_book_drop_chance=法术书掉落几率
config.ebwizardry.generate_loot=生成战利品
config.ebwizardry.firebomb_is_craftable=火焰弹制作
config.ebwizardry.poison_bomb_is_craftable=毒液弹制作
config.ebwizardry.smoke_bomb_is_craftable=烟雾弹制作
config.ebwizardry.use_alternate_scroll_recipe=使用替代卷轴合成
config.ebwizardry.teleport_through_unbreakable_blocks=传送穿过不可破坏的方块
config.ebwizardry.show_summoned_creature_names=显示召唤生物名称
config.ebwizardry.friendly_fire=友军伤害
config.ebwizardry.telekinetic_disarmament=隔空取物解除装备
config.ebwizardry.discovery_mode=探索模式
config.ebwizardry.enable_shift_scrolling=启用 Shift-_滚轮
config.ebwizardry.minion_revenge_targeting=仆从反击目标
config.ebwizardry.player_damage_scaling=玩家伤害比例因数
config.ebwizardry.npc_damage_scaling=NPC伤害比例因数
config.ebwizardry.cast_command_multiplier_limit=Cast指令倍数限制
config.ebwizardry.summoned_creature_targets_whitelist=召唤生物的目标白名单
config.ebwizardry.summoned_creature_targets_blacklist=召唤生物的目标黑名单
config.ebwizardry.spell_hud_position=法术HUD位置
config.ebwizardry.cast_command_name=Cast Spell指令名字
config.ebwizardry.discoverspell_command_name=Discover Spell指令名字
config.ebwizardry.ally_command_name=设置Ally指令名字
config.ebwizardry.allies_command_name=查看Allies指令名字
config.ebwizardry.mobs_immune_to_fire=免疫火焰的怪物
config.ebwizardry.mobs_immune_to_ice=免疫冰冻的怪物
config.ebwizardry.mobs_immune_to_lightning=免疫闪电的怪物
config.ebwizardry.mobs_immune_to_wither=免疫凋零的怪物
config.ebwizardry.mobs_immune_to_poison=免疫毒液的怪物
config.ebwizardry.tower_rarity.tooltip=巫师塔的稀有度,数字越高越罕见。设置为0完全禁用巫师塔。
config.ebwizardry.ore_dimensions.tooltip=水晶矿石生成的维度ID。请注意,从这个列表中删除主世界(id 0)这将使得这个mod非常难玩。
config.ebwizardry.flower_dimensions.tooltip=水晶花会自动生成的维度ID。
config.ebwizardry.tower_dimensions.tooltip=巫师塔生成维度ID的列表。
config.ebwizardry.spell_book_drop_chance.tooltip=怪物死亡时掉落法术书的几率,数字越大,掉的越多。设置为0可以关闭法术书的掉落,设置200保证掉落。
config.ebwizardry.generate_loot.tooltip=是否在地牢箱子中生成战利品。
config.ebwizardry.firebomb_is_craftable.tooltip=是否可以制造火焰弹。
config.ebwizardry.poison_bomb_is_craftable.tooltip=是否可以制造毒液弹。
config.ebwizardry.smoke_bomb_is_craftable.tooltip=是否可以制造烟雾弹。
config.ebwizardry.use_alternate_scroll_recipe.tooltip=是否需要魔法水晶在空白卷轴中无序合成中,如果另一个mod添加配方冲突,则设置为true。
config.ebwizardry.teleport_through_unbreakable_blocks.tooltip=是否允许玩家使用相位来穿过不可破坏的方块(如 基岩)。
config.ebwizardry.show_summoned_creature_names.tooltip=是否将召唤的生物名字和所有者显示在头顶。
config.ebwizardry.friendly_fire.tooltip=是否允许玩家使用魔法伤害他们的盟友。
config.ebwizardry.telekinetic_disarmament.tooltip=是否允许玩家使用隔空取物来解除其他玩家的装备。ebwizardry:设置为false防止物品被盗。
config.ebwizardry.discovery_mode.tooltip=对于那些喜欢神秘的人!当设置为true时,你还没施放的法术不可读,知道施放后(基于这个世界)。在创造模式下无效,如果这是false,在生存模式下无法获得待鉴定卷轴。
config.ebwizardry.enable_shift_scrolling.tooltip=是否可以在滑翔的时候使用鼠标滚轮切换法杖上的法术。请注意,这只会影响到你,同一个服务器的其他玩家只会按照他们自己的设置。
config.ebwizardry.minion_revenge_targeting.tooltip=如果被召唤生物的主人攻击它们,它们是否可以反击它们的主人。
config.ebwizardry.player_damage_scaling.tooltip=玩家施放法术造成伤害的比例因数, relative to 1.
config.ebwizardry.npc_damage_scaling.tooltip=NPC施放法术造成伤害的比例因数,relative to 1。
config.ebwizardry.cast_command_multiplier_limit.tooltip=输入/cast命令的最大倍数的上限,这是为了阻止玩家意外毁坏存档/服务器。大倍数爆炸会造成极大的延迟-你已经被警告过了!
config.ebwizardry.summoned_creature_targets_whitelist.tooltip=除了默认外,允许召唤生物和巫师攻击实体名单。如果想让召唤的生物攻击它们。请把这个mod的生物添加到这个列表中。实体名称不区分大小写。对于mod实体,以mod ID作为前缀(例如 ebwizardry.wizard)。
config.ebwizardry.summoned_creature_targets_blacklist.tooltip=不允许召唤生物和巫师进行攻击的默认设置和白名单。如果允许它们进行攻击会导致问题或是太具破坏性(将爬行者移除这个名单后果自负!)。把这个mod的生物添加到这个列表中。实体名称不区分大小写。对于mod实体,以mod ID作为前缀(例如 ebwizardry.wizard)。
config.ebwizardry.spell_hud_position.tooltip=法术HUD的位置
config.ebwizardry.cast_command_name.tooltip=/cast的命令名称。这是你直接输入/后的应该输入的内容。如果这个设置为“magic”,那么不需要输入/cast,而是输入/magic。
config.ebwizardry.discoverspell_command_name.tooltip=/discoverspell的命令名称。这是你直接输入/后的应该输入的内容。如果这个设置为“magic”,那么不需要输入/discoverspell,而是输入/magic。
config.ebwizardry.ally_command_name.tooltip=/ally的命令名称。这是你直接输入/后的应该输入的内容。如果这个设置为“magic”,那么不需要输入/ally,而是输入/magic。
config.ebwizardry.allies_command_name.tooltip=/allies的命令名称。这是你直接输入/后的应该输入的内容。如果这个设置为“magic”,那么不需要输入/allies,而是输入/magic。
config.ebwizardry.mobs_immune_to_fire.tooltip=除了默认外,不受火焰影响的实体名称列表。如果你想让他们不受火焰魔法影响,请把这个mod的生物添加到这个列表中。实体名称不区分大小写。对于mod实体,以mod ID作为前缀(例如 ebwizardry.wizard)。
config.ebwizardry.mobs_immune_to_ice.tooltip=除了默认外,不受冰冻影响的实体名称列表。如果你想让他们不受冰冻魔法影响,请把这个mod的生物添加到这个列表中。实体名称不区分大小写。对于mod实体,以mod ID作为前缀(例如 ebwizardry.wizard)。
config.ebwizardry.mobs_immune_to_lightning.tooltip=除了默认外,不受闪电影响的实体名称列表。如果你想让他们不受闪电魔法影响,请把这个mod的生物添加到这个列表中。实体名称不区分大小写。对于mod实体,以mod ID作为前缀(例如 ebwizardry.wizard)。
config.ebwizardry.mobs_immune_to_wither.tooltip=除了默认外,不受凋零影响的实体名称列表。如果你想让他们不受凋零魔法影响,请把这个mod的生物添加到这个列表中。实体名称不区分大小写。对于mod实体,以mod ID作为前缀(例如 ebwizardry.wizard)。
config.ebwizardry.mobs_immune_to_poison.tooltip=除了默认外,不受毒液影响的实体名称列表。如果你想让他们不受毒液魔法影响,请把这个mod的生物添加到这个列表中。实体名称不区分大小写。对于mod实体,以mod ID作为前缀(例如 ebwizardry.wizard)。
wizard.debug=%1$s, %2$s, %3$s
@@ -7,7 +7,8 @@
],
"key": {
"v": {
"item": "minecraft:gold_nugget"
"type": "forge:ore_dict",
"ore": "nuggetGold"
},
"w": {
"item": "minecraft:carpet",
@@ -17,7 +18,8 @@
"item": "ebwizardry:magic_crystal"
},
"y": {
"item": "minecraft:lapis_block"
"type": "forge:ore_dict",
"ore": "blockLapis"
},
"z": {
"type": "forge:ore_dict",
@@ -0,0 +1,14 @@
{
"type": "minecraft:crafting_shapeless",
"ingredients": [
{
"item": "minecraft:paper"
},
{
"item": "minecraft:string"
}
],
"result": {
"item": "ebwizardry:blank_scroll"
}
}
@@ -1,5 +1,6 @@
{
"type": "minecraft:crafting_shapeless",
"group": "magic_crystal",
"ingredients": [
{
"item": "ebwizardry:crystal_block"
@@ -7,6 +8,6 @@
],
"result": {
"item": "ebwizardry:magic_crystal",
"amount": 9
"count": 9
}
}
@@ -0,0 +1,13 @@
{
"type": "minecraft:crafting_shapeless",
"group": "magic_crystal",
"ingredients": [
{
"item": "ebwizardry:crystal_flower"
}
],
"result": {
"item": "ebwizardry:magic_crystal",
"count": 2
}
}
@@ -0,0 +1,21 @@
{
"type": "minecraft:crafting_shapeless",
"ingredients": [
{
"item": "minecraft:blaze_powder"
},
{
"item": "minecraft:blaze_powder"
},
{
"item": "minecraft:glass_bottle"
},
{
"item": "minecraft:gunpowder"
}
],
"result": {
"item": "ebwizardry:firebomb",
"count": 3
}
}
@@ -0,0 +1,20 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
" x ",
"xyx",
" x "
],
"key": {
"x": {
"item": "ebwizardry:magic_crystal"
},
"y": {
"item": "minecraft:book"
}
},
"result": {
"item": "ebwizardry:spell_book",
"data": 1
}
}
@@ -0,0 +1,24 @@
{
"type": "forge:ore_shaped",
"pattern": [
" z",
" y ",
"x "
],
"key": {
"x": {
"type": "forge:ore_dict",
"ore": "nuggetGold"
},
"y": {
"type": "forge:ore_dict",
"ore": "stickWood"
},
"z": {
"item": "ebwizardry:magic_crystal"
}
},
"result": {
"item": "ebwizardry:magic_wand"
}
}
@@ -0,0 +1,21 @@
{
"type": "minecraft:crafting_shapeless",
"ingredients": [
{
"item": "minecraft:spider_eye"
},
{
"item": "minecraft:spider_eye"
},
{
"item": "minecraft:glass_bottle"
},
{
"item": "minecraft:gunpowder"
}
],
"result": {
"item": "ebwizardry:poison_bomb",
"count": 3
}
}
@@ -0,0 +1,35 @@
{
"type": "minecraft:crafting_shapeless",
"ingredients": [
[
{
"item": "minecraft:coal",
"data": 0
},
{
"item": "minecraft:coal",
"data": 1
}
],
[
{
"item": "minecraft:coal",
"data": 0
},
{
"item": "minecraft:coal",
"data": 1
}
],
{
"item": "minecraft:glass_bottle"
},
{
"item": "minecraft:gunpowder"
}
],
"result": {
"item": "ebwizardry:smoke_bomb",
"count": 3
}
}
@@ -213,10 +213,13 @@ Code:
- Corail31
- 12foo
- Shadows-of-Fire
- HellFirePvP
Translations:
- Russian: VilagVil
- Spanish and Mexican Spanish: MadWrist
- Chinese: ZHENGLOC and dragon-evol
Lightning ray sound effect from OhhWowProductions
@@ -213,10 +213,13 @@ Code:
- Corail31
- 12foo
- Shadows-of-Fire
- HellFirePvP
Translations:
- Russian: VilagVil
- Spanish and Mexican Spanish: MadWrist
- Chinese: ZHENGLOC and dragon-evol
Lightning ray sound effect from OhhWowProductions
@@ -307,10 +307,13 @@ Code:
- Corail31
- 12foo
- Shadows-of-Fire
- HellFirePvP
Translations:
- Russian: VilagVil
- Spanish and Mexican Spanish: MadWrist
- Chinese: ZHENGLOC and dragon-evol
Lightning ray sound effect from OhhWowProductions
@@ -307,10 +307,13 @@ Code:
- Corail31
- 12foo
- Shadows-of-Fire
- HellFirePvP
Translations:
- Russian: VilagVil
- Spanish and Mexican Spanish: MadWrist
- Chinese: ZHENGLOC and dragon-evol
Lightning ray sound effect from OhhWowProductions
@@ -218,10 +218,13 @@ Code:
- Corail31
- 12foo
- Shadows-of-Fire
- HellFirePvP
Translations:
- Russian: VilagVil
- Spanish and Mexican Spanish: MadWrist
- Chinese: ZHENGLOC and dragon-evol
Lightning ray sound effect from OhhWowProductions
@@ -0,0 +1,225 @@
PAGEBREAK
LINEBREAK
巫师手册
作者 Electroblob
PAGEBREAK
简介
--------------------
欢迎您,伟大的巫师!本书将会向您阐释奥术的工作原理以及使用它们的方法。
如果您不慎遗失了本书,您可以在工作台上用书和魔法水晶制作一本新的。
PAGEBREAK
内容
--------------------
PAGEBREAK
SECTION 准备工作
准备工作
--------------------
要打开通向巫术的大门,您将会需要以下几样东西:
- 一根法杖,由一粒金粒,一根木棍和一块魔法水晶合成。
- 一个奥术工作台,由三块石头,一块青金石块,两块魔法水晶,两粒金粒和一块紫色地毯合成。
- 一本法术书,它们可以在箱子中找到,由怪物掉落或向巫师们购买。当然您也可以用一本书和四块魔法水晶制作一个初学者的法术“魔法飞弹”。
此外,您将会需要更多的魔法水晶来为您的法杖提供魔力。
PAGEBREAK
SECTION 魔力
魔力
--------------------
魔力是给予巫师们力量的奥术能量。它在自然界中以水晶的形式存在,这些水晶嵌在石缝中,可以在地下被找到。法杖中可以储存魔力,而这些魔力将被塑造为您施展的法术。不同的法术会消耗不同数量的魔力,这取决于它们有多么强大以及它们会持续多久。
将鼠标悬停在法杖上就可以看到其中的魔力储量。
IMAGE CRYSTAL
LINEBREAK
魔法
水晶矿 水晶
PAGEBREAK
SECTION 法杖
法杖
--------------------
法杖是一个巫师的实用之选。有了法杖,您就可以施展任何法术,只要法杖能够承受它的力量(更深入的解释在“等级”一节中)。
法杖有许多不同的种类,但您将从最基本的法杖开始。
拿着法杖时,屏幕的角落会出现一个小小的提示,它会显示当前选择的法术及其图标。此外,如果一个法术被施展了,会有一个冷却条显示还有多久才能再次施展这个法术。
PAGEBREAK
SECTION 法术
法术
--------------------
一根没有法术可施展的法杖是毫无用处的。法术可以通过两种方式被记录下来:永久地记录在书上,或者暂时地记录在卷轴上。
法术书本身没有什么用处,它们是用来将其中记录的法术绑定到法杖上的。法术书可以在世界各处被发现,而且您肯定很快就会找到一本。当您发现了一本法术书时,您可以将鼠标悬停在上面来看一下法术的基本信息,您也可以拿着法术书按下右键来阅读法术的详细信息。
与之相反,卷轴的使用方式是不一样的:拿着卷轴右击将会施展其中绑定的法术,而在这个过程中卷轴将会被摧毁。像法术书一样,卷轴可以在世界各处被发现,但您也可以自己制作它们。首先拿一张纸和一些线合成空白卷轴,然后您可以在奥术工作台上将法术绑定到卷轴上,前提是您拥有关于这个法术的知识。这么做将会消耗与法术的魔力消耗相对应数量的魔法水晶(消耗的魔法水晶个数是向上取整的)。
对于未经训练的人来说,用于书写法术的魔法符文是无法辨识的。为了鉴定一个法术,您当然可以施展它然后看看发生了什么 - 但这么做可能会产生您不想看到的副作用,而且许多法术需要在特定的条件下才能起作用。一种更安全可靠的选择是使用鉴定卷轴,它可以在箱子里找到或向巫师购买。拿着它右击将会鉴定您热键栏中第一个未知的法术书或卷轴,并消耗鉴定卷轴。
如果您需要在一次探险中使用某个法术一两次但又不希望它占用您法杖的一个槽,那卷轴是十分有用的。但值得注意的是卷轴是一种相当没有效率的施法方式。
PAGEBREAK
SECTION 奥术工作台
奥术工作台
--------------------
奥术工作台的外观和附魔台很像,您可以在其中给法杖充能、升级或绑定法术。只要放下它并右击,您就会看到一个界面出现,就像右边展示的一样。
PAGEBREAK
IMAGE WORKBENCH
LINEBREAK
奥术工作台
PAGEBREAK
SECTION 绑定法术
绑定法术
--------------------
要把一个法术绑定到法杖上,只要把法杖放在奥术工作台中央的格子里,然后把法术书放在周围的任意一个格子里并按下“应用”。您至多可以在一根法杖上绑定五个法术,当然这一数量可以通过法杖协调升级来增加。拿着法杖时,您可以通过 NEXT_SPELL_KEY 键和 PREVIOUS_SPELL_KEY 键在不同的法术间切换(按键可以在选项 -> 控制里调整)。您也可以在潜行时上下滚动鼠标滚轮来切换法术。
SECTION 法杖充能
法杖充能
--------------------
要给法杖充能,只要把法杖放在奥术工作台中央的格子里,然后在左侧两个格子靠上的那个放一些魔法水晶并按下“应用”。每个水晶等同于 MANA_PER_CRYSTAL 魔力,而法杖只会吸收它所需要的数量,所以您可以在奥术工作台中储备一些魔力水晶以便随时使用。然而,谨记法杖只能整块地吸收魔法水晶。所以如果法杖仅仅还需要 30 魔力,那么 MANA_PER_CRYSTAL_MINUS_30 魔力就会在充能过程中流失。在内部没有魔力时,所有的法杖都会吸收确定数量的魔法水晶来充能,除非它们拥有法杖存储升级。
SECTION 升级法杖
升级法杖
--------------------
要升级法杖,您需要一本对应等级的(参见“等级”)奥法宝典或者某种法杖升级。这两种东西都可以作为战利品得到或者向巫师购买。要升级法杖,只要把法杖放在奥术工作台中央的格子里,然后在左侧两个格子靠下的那个放上法杖升级并按下“应用”。
法杖升级会提升法杖某一方面的性能。每种法杖升级可以叠加至多三次,而法杖能升级的总次数取决于其等级。升级是不可逆的,无法被重新移除。
PAGEBREAK
SECTION 鲜花与烧瓶
鲜花与烧瓶
--------------------
您很可能时不时在野外见到一些神秘的闪着光芒的花。这些是水晶花,是一种自然产生的魔力来源。它们可以被采集,其中的魔力可以像魔力水晶一样被提取出来。
需要在路上给您的法杖充能?没问题!魔力现在可以被装瓶了。用一个玻璃瓶和八个魔力水晶制作一个魔力瓶并带在身上,当您需要使用它时,将它和您的法杖放在一起合成,法杖就会回复一些魔力,而魔力瓶会被消耗掉。在装瓶过程中魔力会有耗损。
PAGEBREAK
SECTION 等级
等级
--------------------
法杖和法术有四个等级:BASIC_COLOUR新手RESET_COLOURAPPRENTICE_COLOUR学徒RESET_COLOURADVANCED_COLOUR进阶RESET_COLOUR和MASTER_COLOUR大师RESET_COLOUR。每一个等级都比上一个等级更加强大。
BASIC_COLOUR新手RESET_COLOUR法杖是可以被合成出来的法杖。它们至多储存 BASIC_MAX_CHARGE 魔力,并且只能施展新手级的法术。新手法术非常简单,可以被任何人施展并且一般不消耗很多魔力。然而这并不一定意味着等级很高时他们就毫无用处,它们的低消耗使得一些新手法术在您达到大师级之后仍十分有用。
APPRENTICE_COLOUR学徒RESET_COLOUR法杖是新手法杖的下一等级。它们至多储存 APPRENTICE_MAX_CHARGE 魔力,并且可以施展新手和学徒级的法术。学徒法术比起新手法术更令人印象深刻,但通常消耗更高。
ADVANCED_COLOUR进阶RESET_COLOUR法杖十分稀有且比前两级强大得多。它们可以施展除了大师级之外的所有法术,并储存 ADVANCED_MAX_CHARGE 魔力。进阶法术可以赋予巫师超人的力量,例如隐身,并在敌人头上倾泻毁灭。
MASTER_COLOUR大师RESET_COLOUR法杖是现存最强大的法杖。他们至多储存 MASTER_MAX_CHARGE 魔力,并且可以施展任何法术。大师级法术书非常稀有,而大师级法术可以给敌人带来完全的湮灭,甚至可以摧毁世界本身。慎重使用。
PAGEBREAK
SECTION 元素
元素
--------------------
法术分属不同的元素,元素表现了法术的本质,并且在被特定的法杖使用时会有额外的效果。
FIRE_COLOUR火
这也许是最具毁灭性的元素。火元素掌控燃烧、熔岩和爆炸。一位强大的烈焰法师能够在敌人头顶打开地狱之门,并能在这个过程中点燃世界。绝大多数火属性攻击法术会点燃其目标,造成持续伤害。但是,注意火属性法术也许对下界生物毫无效果。
ICE_COLOUR冰
冰元素是一切寒冷之物的集合。冰属性法术通常会减速敌人或完全冻住他们,并且对火属性生物极为有效。冰属性魔法在战斗外同样有用,例如冻结水面来顺利过河。
LIGHTNING_COLOUR闪电
这一元素掌控闪电、风暴和天气。一位强大的风暴法师是一股不可忽视的力量,而且他们中的某些人拥有随意降下闪电的能力。闪电法术通常会同时伤害多个敌人并且自动寻找目标,这使它们成为攻击任何生物的有效手段...但小心爬行者。
NECROMANCY_COLOUR死灵
死灵是属于黑暗、混沌和不死生物的元素。死灵法师十分神秘并且常常被认为是邪恶的,虽然一般不是这回事。死灵法术通常被用来召唤为您而战的生物,甚至可以扭曲敌人的意志。
EARTH_COLOUR大地
大地元素专注于自然界:动物,植物,风,凡此种种。大地魔法差异巨大且呈现形式多种多样,从让敌人中毒到释放大气的怒火。大地法术是攻击、防御和实用的综合。
SORCERY_COLOUR妖术
妖术是操纵力和变化的元素。妖术法师操纵光、重力甚至是现实本身来迎合他们的需要。妖术也可以用在别的领域,例如赋予施法者魔法力量或者用意念移动物体。
HEALING_COLOUR治愈
治愈元素掌控防御和再生。治愈法师尽可能地保护他们自己以及他们的盟友,因此可能是非常难缠的对手。尽管一般不用来攻击,某些治愈法术的净化光芒会对不死生物造成可观的伤害。治愈法术在战斗中是不可或缺的。
不同元素之间并不总是泾渭分明的,并且有些法术展现出除自身外的其他元素的特点。
如果您很幸运,您可能会邂逅一根元素法杖。这些法杖会让您在施展正确元素的法术时比平时拥有更强的能力。
PAGEBREAK
SECTION 巫师护甲
巫师护甲
--------------------
作为一名巫师,您需要一些东西来保护您免受与您作战的生物的伤害。普通的护甲无法做到这一点。为了最大化利用您的法术,您将会需要巫师护甲:帽子,法袍,护腿和靴子。不像普通的护甲,这些护甲不会损坏。作为替代,它们使用奥术能量来保护穿戴者。这当然意味着它们需要像法杖一样用魔法水晶充能。幸运的是,这些服装并不会消耗很多魔力。像法杖一样用奥术工作台或魔力瓶充能它们,但小心了 - 如果它们没有了魔力,您将发现自己毫无防御力。
您可以用魔法丝绸来制作巫师护甲,魔法丝绸可以用线和一块魔法水晶合成。
那些完全专注于一种元素的巫师有时会穿上特殊的服装来让这一元素获得额外的增强。整套的此类服装十分受某些巫师的追捧而且不容易找到。
传说中最强大的巫师用一种奥术戳记来极大地强化他们的护甲。
PAGEBREAK
SECTION 巫师和巫师塔
巫师和巫师塔
--------------------
别害怕 - 您不是这个世界里唯一的魔法使用者。在您的旅途中,您可能会遇到拥有标志性尖顶的高塔。这些是您巫师同僚的居所。孤独的生活有时可能会让巫师们变得有些性情乖戾,但他们通常是友好的人,并且乐意与您分享他们的知识 - 尽管要付出些代价。交给他们一些珍贵的金属和宝石,您将收获数不尽的奥术奇迹作为回报。但如果您要寻找的是大师级的法术,您需要与专家谈谈才行。
不幸的是,少数巫师并不欢迎访客。这些巫师通常是被放逐的人,并且对任何挡路者都怀有敌意。小心地接近他们,并准备好在强大的魔法洗礼下防卫自己。然而,如果您击败了他们,您就可以将他们的知识全部收入囊中。
PAGEBREAK
SECTION 合成配方
合成配方
--------------------
PAGEBREAK
PAGEBREAK
合成配方
--------------------
PAGEBREAK
PAGEBREAK
合成配方
--------------------
PAGEBREAK
PAGEBREAK
合成配方
--------------------
PAGEBREAK
PAGEBREAK
鸣谢
--------------------
Electroblob's Wizardry
Version VERSION
For Minecraft MCVERSION
Designed, coded and textured by Electroblob
Thanks to Minecraft Forge and MCP, without which this mod would not have been possible.
Thanks also to the Minecraft modding community, which always has an answer to my modding problems!
In addition, I'd like to thank the following individuals for their contributions to the mod:
Code:
- Corail31
- 12foo
- Shadows-of-Fire
- HellFirePvP
Translations:
- Russian: VilagVil
- Spanish and Mexican Spanish: MadWrist
- Chinese: ZHENGLOC and dragon-evol
Lightning ray sound effect from OhhWowProductions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

+2 -2
View File
@@ -2,9 +2,9 @@
{
"modid" : "ebwizardry",
"name" : "Electroblob's Wizardry",
"version" : "4.1.1",
"version" : "4.1.3",
"url" : "https://minecraft.curseforge.com/projects/electroblobs-wizardry",
"credits" : "Designed, coded and textured by Electroblob. Code contributed to 1.11 and 1.12 updates by Corail31 and 12foo. Translators: MadWrist (Spanish, Mexican Spanish), VilagVil (Russian).",
"credits" : "Designed, coded and textured by Electroblob. Code contributed by: Corail31, 12foo, Shadows-of-Fire, HellFirePvP. Translators: MadWrist (Spanish, Mexican Spanish), VilagVil (Russian), ZHENGLOC/dragon-evol (Chinese).",
"authors" : [
"Electroblob"
],