Compare commits

...

109 Commits

Author SHA1 Message Date
WinDanesz e41f83a2dd build: 4.3.9 -> 4.3.10 version bump 2023-06-28 16:06:37 +02:00
WinDanesz 69b52cfe88 feat: A new ArtefactCheckEvent for addons, allowing devs to consider an artefact active (in slot) conditionally, or even prevent its usage based on custom conditions 2023-06-28 16:06:07 +02:00
WinDanesz 7591821e57 feat: A more Wizardry-native support for BELT, BODY, HEAD and TRINKET artefact types (expanded ItemArtefact.Type) intended for addons 2023-06-28 16:02:32 +02:00
WinDanesz 0ce0dcf2e9 feat: Configuration options for the values of: POTENCY_INCREASE_PER_TIER, COOLDOWN_REDUCTION_PER_LEVEL, DURATION_INCREASE_PER_LEVEL, RANGE_INCREASE_PER_LEVEL, BLAST_RADIUS_INCREASE_PER_LEVEL, RANGE_INCREASE_PER_LEVEL 2023-06-28 15:20:00 +02:00
WinDanesz 73811c3a6b feat: Config option to toggle wands not decrementing cooldowns outside of hands 2023-06-28 14:56:01 +02:00
WinDanesz 2a887b7794 fix: Fixed bug with wands not decrementing cooldowns in the offhand 2023-06-28 14:25:15 +02:00
WinDanesz ad9f482e76 fix: Fixed a bug that prevented NPCs (wizards) from casting certain buff spells 2023-06-28 13:55:09 +02:00
WinDanesz 6eaef94459 Fixed Mark Sacrifice reducing damage at amplifier level 0 2023-03-23 22:01:51 +01:00
ZettaSword 4f5c616240 Added missing sound for the Mirage spell (#835)
Because of "[Client thread/WARN]: Missing sound for event: ebwizardry:spell.mirage" in latest.log i found that Mirage spell has no effect, even if it's registered. That's why with this request i add it to sounds.json.
2023-01-11 15:50:07 +01:00
WinDanesz f5947dded9 chore: version bump to 4.3.9 2022-12-31 20:23:14 +01:00
WinDanesz 77e0acc16b fix: Fixed Curse of Undeath breaking wizard headgear. It no longer breaks hats, and the curse sets the player on fire if the hat has no mana. Fixes #820 2022-12-31 20:21:19 +01:00
WinDanesz e48646c5ff feat: Conjured bows will now shoot conjured arrows 2022-12-31 20:14:47 +01:00
WinDanesz 5e48fe51ea fix: Added missing import 2022-12-31 19:58:02 +01:00
WinDanesz 6b30dbef65 fix: Fixed onImbuementRemoval() not being called for imbuements expired in the inventory. Currently this bug was only affecting adons. Fixes #833 2022-12-31 19:52:11 +01:00
WinDanesz d6508a2be4 fix: Fixed Fire Skin potion effect's retaliatory burn duration (was 20x shorter than intended) 2022-12-31 19:51:43 +01:00
WinDanesz dfcadfb3bd fix: No more console spam from Muffle spell 2022-10-04 00:55:06 +02:00
ZettaSword 7888b92129 feat: Wand cooldown only decrements if the player holds the wand 2022-08-04 22:17:31 +02:00
ZettaSword 5b48dffa77 fix: Fixed the adaptive brightness of Oak/Iron/Diamondflesh 2022-08-04 22:15:06 +02:00
WinDanesz 5bf4650da1 fix: Fixed wizards not using addon book spells 2022-07-11 21:14:45 +02:00
WinDanesz 8e9c270b77 fix: Fixed wizards selling addon book spells with the default book 2022-07-11 21:13:38 +02:00
WinDanesz 00080331df feat: Reworked the Summon Iron Golem spell, its new name is Summon Spectral Golem 2022-07-08 22:18:59 +02:00
WinDanesz 27e40e2069 fix: Fixed the opacity of conjured arrows 2022-07-08 21:37:55 +02:00
WinDanesz 3a93877de3 fix: Fire Ring shouldn't instantly melt away players on servers anymore 2022-07-08 21:11:10 +02:00
WinDanesz 7f70784cd3 fix: Fixed Scrolls of continuous spells having a cooldown in creative mode 2022-07-08 20:36:46 +02:00
WinDanesz ed6e3df66e feat: The Arrow Rain spell summons conjured arrows 2022-07-08 20:32:22 +02:00
WinDanesz eb5becbbd4 fix: Fixed some addon crystals restoring more mana than they should
Fixes #816
2022-07-08 19:41:25 +02:00
WinDanesz 9599316fbc fix: Added a config option to prevent crash with guidebook loading on some locales. Note that if you use this config, you won't have the Wizard's Handbook in an usable state!
Fixes #815, Fixes #814, Fixes #800, Fixes #768
2022-07-08 19:30:03 +02:00
WinDanesz cc1c951ef8 feat: Soulwalker's Ring only soulbounds an entity for 20 seconds 2022-07-08 19:20:16 +02:00
WinDanesz d23c4cba18 feat: Forcefield loses 1% durability each time it repulses an enemy or a projectile 2022-07-08 19:16:54 +02:00
WinDanesz 3d30b0b96f feat: Forcefield loses 2% durability each time it repulses an enemy or a projectile 2022-06-22 22:38:54 +02:00
WinDanesz ad1e5d555a feat: Reworked the Oakflesh, Ironflesh and Diamondflesh spells 2022-06-22 22:24:30 +02:00
WinDanesz 14ea5f1c72 fix: Fixed Containment spell for entities 2022-06-19 23:25:36 +02:00
WinDanesz 709d44e4d9 feat: Class Armour sets (Sage, Warlock, Battlemage) only grant their set bonuses if each armour piece has mana 2022-06-19 12:44:14 +02:00
WinDanesz 8df00e9c41 feat: Added potency_per_level spell property for Empowerment, reduced potency gain per level 0.25->0.15 2022-06-13 23:12:14 +02:00
WinDanesz 8dbb0ec058 fix: Fixed 'Ward I' effect not giving any protection against magic 2022-06-12 23:33:07 +02:00
WinDanesz b8310eedae feat: Added a player_effect_duration_multiplier for the Paralysis spell, defaults to 0.5 2022-06-12 00:12:24 +02:00
WinDanesz c04754afe1 chore: version bump to v4.3.7 2022-04-17 21:37:20 +02:00
WinDanesz 3155aa6815 fix: Should fix the disconnect issue when pretty much all existing spell packs are present in the game
Mods were registering spells on the client and server side in a different order (perhaps related to the OS), causing a mismatch in spell networkIDs. This will ensure that spells are sorted alphabetically and redistributes a new ID.
2022-04-17 20:43:59 +02:00
WinDanesz ea27b1a081 Revert "Merge pull request #750 from WinDanesz/patch-1226-2" 2022-04-17 15:53:48 +02:00
WinDanesz 4d078f9597 Revert "Fixed crash on dedicated servers (PacketSpellProperties), Fixes #780, #779, #773, #774, #771, #768"
This reverts commit 6690564017.
2022-04-17 15:46:11 +02:00
WinDanesz 67459cbbbd chore: Delete feature_request.md 2022-04-15 14:06:33 +02:00
WinDanesz 932de4e969 chore: Delete question.md 2022-04-15 13:58:44 +02:00
WinDanesz 41e28291ad chore: create config.yml 2022-04-15 13:58:29 +02:00
WinDanesz 6ae6324368 chore: Rename bug_report.md to bug_report.yml 2022-04-15 13:52:10 +02:00
WinDanesz 4858716f05 chore: update bug_report.md 2022-04-15 13:51:44 +02:00
WinDanesz 24fb4cfe4a v4.3.6 2022-03-06 19:26:45 +01:00
WinDanesz 186138d0c0 fixed visibility modifier of ImbuementActivateEvent's fields 2022-03-06 19:26:04 +01:00
WinDanesz 6690564017 Fixed crash on dedicated servers (PacketSpellProperties), Fixes #780, #779, #773, #774, #771, #768 2022-03-06 19:14:47 +01:00
WinDanesz 89a0a900cc v4.3.5 2022-02-07 23:06:39 +01:00
WinDanesz 391a24db3f Fixes integration with Construct's Armory and other mod's unbreakable helmets. #547 2022-02-07 22:10:28 +01:00
WinDanesz 4b546af642 Added a new ImbuementActivateEvent to allow addons hooking into the imbuement process 2022-02-07 21:50:26 +01:00
WinDanesz ee8aabbf97 This might fix the lingering Frost effect (from Frost Ray) 2022-02-07 21:37:01 +01:00
Rodro 45994e2b94 Fixed player rubberbanding when touching the wall of a containment field. Fixes #469 (Rodrogamby)
This fixed player rubberbanding when touching the wall of a containment field for me.

I took the liberty of uncommenting some code which produces a sound when the player tries to leave the field, and also deleted line 113 along with everything related to it since it seemed unnecessary.

I've tested this on singleplayer and on my 200ms multiplayer server and appears to be working perfectly in both.
(It works even if allow-flight is set to false on server.properties; I also tried using an elytra, levitation effect and extra speed, which all worked well too).
All tests were done using Forge-2860
2022-02-06 22:19:32 +01:00
WinDanesz 13bdc69da8 Added support for Forge's in-game mod version update notifier 2022-02-05 23:04:14 +01:00
WinDanesz c0184fde8e Fixed a bug with EntityWizard using one of EntityEvilWizard's DataParameter 2022-02-05 22:48:35 +01:00
WinDanesz cbd297e59d updated gradle version 2022-02-05 22:48:34 +01:00
WinDanesz c6cf7c950e increased duplicate detect threshold 2022-02-03 14:49:37 +01:00
WinDanesz fe5d80e017 Fixed dispenser crash with Conjure Block spell. Fixes #735 2022-02-03 11:57:22 +01:00
WinDanesz e985a8f15b Fixed dispenser crash with Slime spell. Fixes #735 2022-02-03 11:57:22 +01:00
Electroblob 615767f758 Merge pull request #688 from WinDanesz/1.12.2.dev
added onImbuementRemoval(ItemStack stack) to Imbuement interface
2022-02-01 18:34:24 +00:00
Electroblob 65a24b2295 Merge pull request #744 from WinDanesz/patch-2
Added duplicate issue detector & labeling tool
2022-02-01 18:33:18 +00:00
Electroblob 94c2afe67a Merge pull request #747 from WinDanesz/patch-1225-2
Fixes Mark Sacrifice not doing damage with low spell potency
2022-02-01 18:32:02 +00:00
Electroblob 9bbca37ecd Merge pull request #749 from WinDanesz/patch-1225-4
Scrolls no longer have cooldown in Creative mode
2022-02-01 18:30:47 +00:00
Electroblob 58241a0f5c Merge pull request #748 from WinDanesz/patch-1225-3
Added getter for ItemArtefact.enabled
2022-02-01 18:28:21 +00:00
Electroblob a960a01ca1 Merge pull request #750 from WinDanesz/patch-1226-2
Splitting PacketSpellProperties into batches of 100 spells.
2022-02-01 18:27:47 +00:00
Electroblob 67d8ee773c Merge pull request #751 from WinDanesz/patch-1227-1
Added tooltip for Spell Book and Scroll items, displaying the spell's…
2022-02-01 18:27:25 +00:00
Electroblob c6f2675278 Merge pull request #753 from WinDanesz/patch-1228-1
Fixed bug with wizard armours always providing protection even withou…
2022-02-01 18:26:54 +00:00
Electroblob77 2380be230e Merge branch '1.12.2' of https://github.com/Electroblob77/Wizardry into 1.12.2 2022-02-01 18:24:34 +00:00
Electroblob77 833276b7b3 TODOs 2022-02-01 18:24:26 +00:00
Electroblob77 9b32835720 Add resurrection event 2022-02-01 18:24:17 +00:00
Electroblob77 61634a9cc3 Change resurrection wait time and add particles to indicate where an ally died 2022-02-01 18:23:47 +00:00
Electroblob 408a35db8d Merge pull request #754 from WinDanesz/patch-1228-2
Remove soulbinding curse effect if the potion is no longer active. fi…
2022-02-01 18:20:37 +00:00
Electroblob 9695a85131 Merge pull request #755 from WinDanesz/patch-0102-1
Frostbite effect and burning now cancels each other
2022-02-01 18:20:20 +00:00
Electroblob d027cf4f2a Merge pull request #756 from WinDanesz/patch-0103-1
Added injectMobDrops setting to easily disable mob loot injection for…
2022-02-01 18:19:29 +00:00
WinDanesz c2f8bfc5b4 Added injectMobDrops setting to easily disable mob loot injection for all entities 2022-01-03 14:47:33 +01:00
WinDanesz 486425a62c Frostbite effect and entity burning now cancels each other 2022-01-02 22:07:05 +01:00
WinDanesz f9681d4c66 Remove soulbinding curse effect if the potion is no longer active. fixes #619. 2021-12-28 16:10:31 +01:00
WinDanesz cd0671dc59 Fixed bug with wizard armours always providing protection even without mana. Fixes #752 2021-12-28 16:08:18 +01:00
WinDanesz 7ebca16948 Added tooltip for Spell Book and Scroll items, displaying the spell's source mod if it's from an addon 2021-12-27 11:31:07 +01:00
WinDanesz e8cbdde518 Splitting PacketSpellProperties into batches of 100 spells. Fixes world load issue with large list of spells 2021-12-26 22:08:29 +01:00
WinDanesz 7ca6f05151 Scrolls no longer have cooldown in Creative mode 2021-12-25 18:16:32 +01:00
WinDanesz f4f17e90e5 Added getter for ItemArtefact.enabled 2021-12-25 18:10:09 +01:00
WinDanesz 3ea48efb1d Fixes Mark Sacrifice not doing damage with a potion amplifier of 0 2021-12-25 18:01:43 +01:00
WinDanesz ffc3533688 Create potential-duplicates.yml 2021-12-20 18:36:08 +01:00
Electroblob bd309855a2 Merge pull request #721 from WinDanesz/1.12.2-PR-10-02
Fixes wizards being stuck in a continuous, client-side only spellcast…
2021-10-03 18:10:51 +01:00
WinDanesz 1473c7e9b7 Fixes wizards being stuck in a continuous, client-side only spellcasting loop of their continuous spells if their target dies 2021-10-02 00:26:31 +02:00
WinDanesz 15cc7b6d18 added isEnabled() public method to ItemArtefact 2021-07-07 13:26:21 +02:00
WinDanesz 1c89c5f779 added onImbuementRemoval(ItemStack stack) to Imbuement interface 2021-07-07 12:40:05 +02:00
Electroblob77 ca7f1cc8ca Prevent Hyeleth's amulet from casting the shield spell from a scroll, fixes #680 2021-06-20 23:44:04 +01:00
Electroblob77 8fd1de84e4 Fix next/previous section button weirdness 2021-06-19 16:19:22 +01:00
Electroblob77 95d9168b6b Fix hyperlink wrapping for spaceless languages and remove remaining newlines 2021-06-19 16:01:23 +01:00
Electroblob77 c1db827132 Remove manual newline characters from Chinese handbook translations
I'm not 100% sure which to remove so I've only removed single newlines in block text for now
2021-06-19 13:01:58 +01:00
Electroblob77 d10b78ab46 Ignore hyperlink suffixes in spaceless languages, fixes #620
There's no real way to do this other than hardcoding which languages are exceptions (currently only the two Chinese locales)
2021-06-19 13:01:47 +01:00
Electroblob77 2d70523f43 Remove obsolete plain text Russian handbook translation 2021-06-19 12:47:00 +01:00
Electroblob77 42fb7ad3df Have all the baked bookshelf models use the same set of book models, fixes #621
This effectively cuts the number of book models by a factor equal to the number of bookshelf variants, which is 6 in the base mod
2021-06-19 00:01:24 +01:00
Electroblob77 e90d0950d4 Replace glide end sound with dummy sound (which for some reason seems not to play at all? Oh well ¯\_(ツ)_/¯), fixes #646 2021-06-18 17:47:55 +01:00
Electroblob77 888d4190d1 Store static map of mana flask charging recipes rather than iterating, fixes #671 2021-06-18 17:26:40 +01:00
Electroblob77 57696b2538 Make all forfeits respect claims via the methods in BlockUtils, fixes #672 2021-06-18 16:27:57 +01:00
Electroblob77 1440537f6b Missed one! 2021-06-18 14:23:40 +01:00
Electroblob77 a16ff88c8d Update credits (and put the discord mods in their rightful place at the top of the list <3) 2021-06-18 14:21:21 +01:00
Electroblob77 041de12ea7 Update Russian translations, courtesy of DrHesperus 2021-06-18 13:52:01 +01:00
Electroblob77 5e36f66c4e Update Korean translations, courtesy of red1854th 2021-06-18 13:51:32 +01:00
Electroblob77 a6a5a6104d Update French translations, courtesy of Crowller 2021-06-18 13:50:53 +01:00
Electroblob77 6f7b225ce8 ParticleBuilder is not thread-safe! 2021-06-18 13:49:45 +01:00
Electroblob77 81a85883d2 Consume mana/scrolls when forfeits are triggered, fixes #673 2021-06-18 13:49:29 +01:00
Electroblob 3f06d2fea4 Update bug_report.md 2021-06-18 00:08:29 +01:00
Electroblob 26b390268a Update ISSUE_TEMPLATE.md 2021-06-18 00:08:12 +01:00
Electroblob 486d55f349 Merge pull request #636 from LWHK/class-build
Add LF for CHS translation
2021-03-03 16:08:01 +00:00
TUsama 5948090d63 add LF manually
add LF manually
2021-03-01 17:55:32 +08:00
103 changed files with 3535 additions and 1920 deletions
+7
View File
@@ -0,0 +1,7 @@
{
"homepage": "https://www.curseforge.com/minecraft/mc-mods/electroblobs-wizardry",
"promos": {
"1.12.2-latest": "4.3.10",
"1.12.2-recommended": "4.3.10"
}
}
-20
View File
@@ -1,20 +0,0 @@
---
name: Bug report
about: Report a crash or something that isn't working as it should
title: "[Give a brief, relevant title here]"
labels: bug
assignees: ''
---
Please read the [guide for contributing](https://github.com/Electroblob77/Wizardry/blob/1.12.2/CONTRIBUTING.md) before posting.
Minecraft version: 1.12.2 [change as necessary]
Wizardry version: 4.3.4 [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.]
Other mods involved: [only list mods that are relevant to the problem]
Link to crash report (if applicable): [give a link to the crash report on gist, pastebin, etc.]
+85
View File
@@ -0,0 +1,85 @@
name: 🐛 Bug Report
description: Something is not working as expected
title: "[Bug] <write the title here>"
labels: [ "bug", "Needs Triage" ]
body:
- type: markdown
attributes:
value: |
Please read the [guide for contributing](https://github.com/Electroblob77/Wizardry/blob/1.12.2/CONTRIBUTING.md) before posting. You may also find the [troubleshooting page](https://github.com/Electroblob77/Wizardry/wiki/Troubleshooting) helpful.
Please try the latest version of the mod and check if the issue persist before submitting a report.
- type: checkboxes
attributes:
label: Is there an existing issue for this?
description: Please search to see if an issue already exists for the bug you encountered.
options:
- label: I have searched the existing issues
required: true
- type: textarea
id: observed
attributes:
label: Observed behaviour
description: Describe what happened and when this happened
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected behaviour
description: Describe what you expected to happen
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: Steps to reproduce
description: Step by step instructions on how to reproduce the observed behaviour
placeholder: |
1. Join a server
2. Cast the [spell]
3. ...
validations:
required: true
- type: input
id: crashlog
attributes:
label: Crashlog
description: If this was a crash, grab [minecraft instance]/logs/debug.log, upload it as a [gist](https://gist.github.com/) and paste the link here. Alternatively, give a link to the crash report on gist, pastebin if you already have one there.
placeholder: https://gist.github.com/<your-user>/abcdef124
- type: dropdown
id: environment
attributes:
label: Environment (Singleplayer/Server, etc.)
options:
- Singleplayer
- LAN game/Server
- Issue present on both sides
- Not sure
validations:
required: true
- type: input
id: mod-version
attributes:
label: Mod version
placeholder: 1.0.0
validations:
required: true
- type: input
id: minecraft-version
attributes:
label: Minecraft version
placeholder: 12.2.2
validations:
required: true
- type: input
id: forge-version
attributes:
label: Forge version
placeholder: 1.12.2 - 14.23.5.2860
validations:
required: true
- type: textarea
id: other-mods
attributes:
label: Other mods
description: List any other mods present when the bug was encountered, include the mod versions. You only have to fill this if no crash log was attached
+14
View File
@@ -0,0 +1,14 @@
blank_issues_enabled: false
contact_links:
- name: 📖 Mod Wiki Page
url: https://github.com/Electroblob77/Wizardry/wiki
about: Most features are documented in the mod's wiki page --- Link --->
- name: 💬 Electroblob's Wizardry discord
url: https://discord.gg/hs8yJP2
about: Ask for help or get more info on Discord. --- Discord Server link --->
- name: 💡 Feature requests / suggestions
url: https://discord.gg/hs8yJP2
about: Please use the discord server to suggest stuff. --- Discord Server link --->
- name: ❓ Question
url: https://discord.gg/hs8yJP2
about: Ask a question about the mod or the code. --- Discord Server link --->
-16
View File
@@ -1,16 +0,0 @@
---
name: Feature request
about: Make a suggestion for improving the mod
title: "[Give a brief, relevant title here]"
labels: enhancement
assignees: ''
---
Please read the [guide for contributing](https://github.com/Electroblob77/Wizardry/blob/1.12.2/CONTRIBUTING.md) before posting.
Minecraft versions: [if this suggestion only applies to some versions, list them here]
Suggestion details: [describe what you would like to see added to the mod and why]
Other mods involved: [if this suggestion involves integration with other mods, list them here]
-17
View File
@@ -1,17 +0,0 @@
---
name: Question
about: Ask a question about the mod or the code
title: "[Give a brief, relevant title here]"
labels: question
assignees: ''
---
Please read the [guide for contributing](https://github.com/Electroblob77/Wizardry/blob/1.12.2/CONTRIBUTING.md) before posting.
Minecraft version: 1.12.2 [change as necessary]
Wizardry version: 4.3.4 [change as necessary]
Question details: [explain your question here]
Other mods involved: [if this question involves other mods, list them here]
@@ -0,0 +1,38 @@
name: Potential Duplicates
on:
issues:
types: [opened, edited]
jobs:
run:
runs-on: ubuntu-latest
steps:
- uses: bubkoo/potential-duplicates@v1
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
label: potential duplicate
exclude: |
adding
add
creating
create
icons
icon
logos
logo
missing
miss
needing
need
please
requesting
request
1.12.2
wizardry
state: all
threshold: 0.7
comment: |
This issue is potentially a duplicate of one of the following issues:
{{#issues}}
- [#{{ number }}] {{ title }} ({{ accuracy }}% match)
{{/issues}}
+8 -2
View File
@@ -1,7 +1,7 @@
# Credits
Electroblob's Wizardry
Version 4.3.4
Version 4.3.7
For Minecraft 1.12.2
Designed, coded and textured by Electroblob
@@ -12,6 +12,11 @@ Thanks also to the Minecraft modding community, which always has an answer to my
In addition, I'd like to thank the following individuals for their contributions to the mod:
#### Discord Moderators (and all-round awesome people)
- FavouriteDragon
- WinDanesz
#### Code
- Corail31
@@ -27,13 +32,14 @@ In addition, I'd like to thank the following individuals for their contributions
- rafasoares
- xinyuan-liu
- SettingDust
- Aralu115
#### Translations
- Spanish: MadWrist, Alsentar
- Mexican Spanish: MadWrist
- Russian: VilagVil, kellixon, bigenergy, MugGod2, DrHesperus
- French: Hahdrim
- French: Hahdrim, Crowller
- Brazilian Portuguese: lorrampi
- Chinese (Simplified): ZHENGLOC, dragon-evol, Hokorizero, TUsama, Determancer
- Korean: shejery, rewi_wire, 방통, red1854th
+2 -2
View File
@@ -1,7 +1,7 @@
Please read the [guide for contributing](https://github.com/Electroblob77/Wizardry/blob/1.12.2/guide_for_contributing.md) before posting.
Please read the [guide for contributing](https://github.com/Electroblob77/Wizardry/blob/1.12.2/guide_for_contributing.md) before posting. You may also find the [troubleshooting page](https://github.com/Electroblob77/Wizardry/wiki/Troubleshooting) helpful.
Minecraft version: 1.12.2 [change as necessary]
Wizardry version: 4.3.4 [change as necessary]
Wizardry version: [change as necessary]
Environment: Singleplayer/LAN game/Server [delete as necessary]
Issue details: [describe what you were doing when the issue occurred, what went wrong, what you expected to happen, etc.]
+1 -1
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.3.4" // There, it matches semver, happy now?
version = "4.3.10"
group= "electroblob.wizardry"// http://maven.apache.org/guides/mini/guide-naming-conventions.html
archivesBaseName = "ElectroblobsWizardry"
Binary file not shown.
+1 -2
View File
@@ -1,6 +1,5 @@
#Mon Sep 14 12:28:28 PDT 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip
Vendored
+61 -53
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/usr/bin/env sh
##############################################################################
##
@@ -6,47 +6,6 @@
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
@@ -61,9 +20,49 @@ while [ -h "$PRG" ] ; do
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -79,18 +78,18 @@ if [ -n "$JAVA_HOME" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
locations of your Java installation."
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
locations of your Java installation."
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
@@ -114,6 +113,7 @@ fi
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
@@ -154,11 +154,19 @@ if $cygwin ; then
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
APP_ARGS=$(save "$@")
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"
Vendored
+6 -12
View File
@@ -8,14 +8,14 @@
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
@@ -27,7 +27,7 @@ echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo locations of your Java installation.
echo location of your Java installation.
goto fail
@@ -41,15 +41,14 @@ echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo locations of your Java installation.
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
@@ -60,11 +59,6 @@ set _SKIP=2
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
@@ -156,6 +156,12 @@ public final class Settings {
public Pair<ResourceLocation, Short>[] treeBlocks = parseItemMetaStrings(DEFAULT_TREE_BLOCKS);
/** <b>[Server-only]</b> The chance for wizard towers to generate with an evil wizard and chest inside. */
public double evilWizardChance = 0.2;
public double cooldownReductionPerLevel = 0.15;
public double potencyIncreasePerTier = 0.15;
public double durationIncreasePerLevel = 0.25;
public double rangeIncreasePerLevel = 0.25;
public double blastIncreasePerLevel = 0.25;
public double frostSlownessIncreasePerLevel = 0.5;
/** <b>[Server-only]</b> List of dimension ids in which to generate crystal ore. */
public int[] oreDimensions = {0};
/** <b>[Server-only]</b> List of dimension ids in which to generate crystal flowers. */
@@ -198,6 +204,10 @@ public final class Settings {
public boolean blindnessTweak = true;
/** <b>[Server-only]</b> Whether using bonemeal on grass blocks has a chance to grow crystal flowers. */
public boolean bonemealGrowsCrystalFlowers = true;
/** <b>[Server-only]</b> Whether wands only decrement their cooldowns if a player holds them. */
public boolean wandsMustBeHeldToDecrementCooldown = false;
/** <b>[Server-only]</b> Whether to enable Wizardry mob loot injection. Allows an easier switch instead of blacklisting all entities. */
public boolean injectMobDrops = true;
/**
* <b>[Server-only]</b> List of registry names of entities which summoned creatures are allowed to attack, in addition
* to the defaults.
@@ -377,6 +387,9 @@ public final class Settings {
public boolean showSpellHUD = true;
/** <b>[Client-only]</b> Whether to show the charge meter when charging up a spell. */
public boolean showChargeMeter = true;
/** <b>[Client-only]</b> Whether to initialise the handbook's data. Setting this to false will break the in-game handbook, but might help with some
* startup crashes */
public boolean loadHandbook = true;
/** <b>[Client-only]</b> The position of the spell HUD. */
public GuiPosition spellHUDPosition = GuiPosition.BOTTOM_LEFT;
@@ -663,6 +676,13 @@ public final class Settings {
bonemealGrowsCrystalFlowers = property.getBoolean();
propOrder.add(property.getName());
property = config.get(GAMEPLAY_CATEGORY, "wandsMustBeHeldToDecrementCooldown", false,
"Whether wands only decrement their cooldowns if a player holds them.");
property.setLanguageKey("config." + Wizardry.MODID + ".wands_must_be_held_to_decrement_cooldown");
Wizardry.proxy.setToNamedBooleanEntry(property);
wandsMustBeHeldToDecrementCooldown = property.getBoolean();
propOrder.add(property.getName());
checkForRedundantOptions(GAMEPLAY_CATEGORY, propOrder); // Must be before the order is set!
config.setCategoryPropertyOrder(GAMEPLAY_CATEGORY, propOrder);
@@ -807,6 +827,13 @@ public final class Settings {
blindnessTweak = property.getBoolean();
propOrder.add(property.getName());
property = config.get(TWEAKS_CATEGORY, "injectMobDrops", true,
"Whether to inject Wizardry loot to mobs, based on the loot table 'Mob Loot Table Whitelist' / 'Mob Loot Table Blacklist' settings. If disabled, the lists won't have any effect!");
property.setLanguageKey("config." + Wizardry.MODID + ".inject_mob_drops");
Wizardry.proxy.setToNamedBooleanEntry(property);
injectMobDrops = property.getBoolean();
propOrder.add(property.getName());
property = config.get(TWEAKS_CATEGORY, "mobLootTableWhitelist", new String[0], "Whitelist for loot tables to inject additional mob drops (as specified in loot_tables/entities/mob_additions.json) into. Wizardry makes a best guess as to which loot tables belong to hostile mobs, but this may not always be correct or appropriate; add loot table locations (not entity IDs) to this list to manually include them.");
property.setLanguageKey("config." + Wizardry.MODID + ".mob_loot_table_whitelist");
property.setRequiresMcRestart(true);
@@ -914,6 +941,50 @@ public final class Settings {
}
}
property = config.get(TWEAKS_CATEGORY, "cooldown_reduction_per_level", 0.15,
"The fraction by which cooldowns are reduced for each level of cooldown upgrade.",
0.05, Integer.MAX_VALUE); // Sure, I mean you COULD set it to 2^31-1... what could possibly go wrong?
property.setLanguageKey("config." + Wizardry.MODID + ".cast_command_multiplier_limit");
cooldownReductionPerLevel = property.getDouble();
propOrder.add(property.getName());
property = config.get(TWEAKS_CATEGORY, "potency_increase_per_tier", 0.15,
"The fraction by which potency is increased for each tier of matching wand. May cause extreme lag with high values!",
0.05, Integer.MAX_VALUE);
property.setLanguageKey("config." + Wizardry.MODID + ".potency_increase_per_tier");
potencyIncreasePerTier = property.getDouble();
propOrder.add(property.getName());
property = config.get(TWEAKS_CATEGORY, "duration_increase_per_level", 0.25,
"The fraction by which spell duration is increased for each level of duration upgrade.",
0.05, Integer.MAX_VALUE);
property.setLanguageKey("config." + Wizardry.MODID + ".duration_increase_per_level");
durationIncreasePerLevel = property.getDouble();
propOrder.add(property.getName());
property = config.get(TWEAKS_CATEGORY, "range_increase_per_level", 0.25,
"The fraction by which spell range is increased for each level of range upgrade. May cause extreme lag with high values!",
0.05, Integer.MAX_VALUE);
property.setLanguageKey("config." + Wizardry.MODID + ".range_increase_per_level");
rangeIncreasePerLevel = property.getDouble();
propOrder.add(property.getName());
property = config.get(TWEAKS_CATEGORY, "blast_increase_per_level", 0.25,
"The fraction by which spell blast is increased for each level of blast upgrade. May cause extreme lag with high values!",
0.05, Integer.MAX_VALUE);
property.setLanguageKey("config." + Wizardry.MODID + ".blast_increase_per_level");
blastIncreasePerLevel = property.getDouble();
propOrder.add(property.getName());
property = config.get(TWEAKS_CATEGORY, "frost_slowness_increase_per_level", 0.5,
"The fraction by which movement speed is reduced per level of frost effect.",
0.05, Integer.MAX_VALUE);
property.setLanguageKey("config." + Wizardry.MODID + ".frost_slowness_increase_per_level");
frostSlownessIncreasePerLevel = property.getDouble();
propOrder.add(property.getName());
checkForRedundantOptions(TWEAKS_CATEGORY, propOrder); // Must be before the order is set!
config.setCategoryPropertyOrder(TWEAKS_CATEGORY, propOrder);
@@ -1103,6 +1174,13 @@ public final class Settings {
showChargeMeter = property.getBoolean();
propOrder.add(property.getName());
property = config.get(CLIENT_CATEGORY, "loadHandbook", true, "Whether to initialise the in-game handbook. Setting this to false will brick the in-game handbook, but it might help if you have startup crashes.");
property.setLanguageKey("config." + Wizardry.MODID + ".load_handbook");
property.setRequiresWorldRestart(false);
Wizardry.proxy.setToNamedBooleanEntry(property);
loadHandbook = 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());
@@ -1,8 +1,5 @@
package electroblob.wizardry;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import electroblob.wizardry.block.BlockBookshelf;
import electroblob.wizardry.command.CommandCastSpell;
import electroblob.wizardry.command.CommandDiscoverSpell;
@@ -16,11 +13,23 @@ import electroblob.wizardry.inventory.ContainerBookshelf;
import electroblob.wizardry.misc.DonationPerksHandler;
import electroblob.wizardry.misc.Forfeit;
import electroblob.wizardry.packet.WizardryPacketHandler;
import electroblob.wizardry.registry.*;
import electroblob.wizardry.registry.Spells;
import electroblob.wizardry.registry.WizardryAdvancementTriggers;
import electroblob.wizardry.registry.WizardryBlocks;
import electroblob.wizardry.registry.WizardryItems;
import electroblob.wizardry.registry.WizardryLoot;
import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.spell.Spell;
import electroblob.wizardry.util.SpellNetworkIDSorter;
import electroblob.wizardry.util.SpellProperties;
import electroblob.wizardry.util.WandHelper;
import electroblob.wizardry.worldgen.*;
import electroblob.wizardry.worldgen.WorldGenCrystalFlower;
import electroblob.wizardry.worldgen.WorldGenCrystalOre;
import electroblob.wizardry.worldgen.WorldGenLibraryRuins;
import electroblob.wizardry.worldgen.WorldGenObelisk;
import electroblob.wizardry.worldgen.WorldGenShrine;
import electroblob.wizardry.worldgen.WorldGenUndergroundLibraryRuins;
import electroblob.wizardry.worldgen.WorldGenWizardTower;
import net.minecraft.item.Item;
import net.minecraft.util.SoundCategory;
import net.minecraftforge.common.MinecraftForge;
@@ -39,8 +48,6 @@ import net.minecraftforge.fml.common.registry.GameRegistry;
import org.apache.logging.log4j.Logger;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Calendar;
/**
@@ -56,6 +63,7 @@ import java.util.Calendar;
@Mod(modid = Wizardry.MODID, name = Wizardry.NAME, version = Wizardry.VERSION, acceptedMinecraftVersions = "[1.12.2]",
guiFactory = "electroblob.wizardry.WizardryGuiFactory",
updateJSON = Wizardry.updateJSON,
dependencies = "required-after:forge@[14.23.5.2847,);after:jei@[4.15.0,);after:baubles@[1.5.2,);after:antiqueatlas@[4.6,)")
public class Wizardry {
@@ -74,7 +82,13 @@ public class Wizardry {
* 1.x.x represents Minecraft 1.7.x versions, 2.x.x represents Minecraft 1.10.x versions, 3.x.x represents Minecraft
* 1.11.x versions, and so on.
*/
public static final String VERSION = "4.3.4";
public static final String VERSION = "4.3.10";
/**
* Json file used by Forge's built-in <a href="https://mcforge.readthedocs.io/en/1.12.x/gettingstarted/autoupdate/">update checker</a>.
* Used by the in-game mod menu to show that green icon whenever a newer version is available of the mod.
*/
public static final String updateJSON = "https://github.com/Electroblob77/Wizardry/blob/1.12.2/.forge/update.json";
// IDEA: Triggering of inbuilt Forge events in relevant places?
// IDEA: Abstract the vanilla particles behind the particle builder
@@ -113,11 +127,10 @@ public class Wizardry {
public void preInit(FMLPreInitializationEvent event){
logger = event.getModLog();
proxy.registerResourceReloadListeners();
configDirectory = new File(event.getModConfigurationDirectory(), Wizardry.MODID);
settings.initConfig(event);
proxy.registerResourceReloadListeners();
Calendar calendar = Calendar.getInstance();
tisTheSeason = calendar.get(Calendar.MONTH) + 1 == 12 && calendar.get(Calendar.DAY_OF_MONTH) >= 24
@@ -189,6 +202,8 @@ public class Wizardry {
public void postInit(FMLPostInitializationEvent event){
proxy.initialiseLayers();
proxy.initialiseAnimations();
SpellNetworkIDSorter.init();
}
@EventHandler
@@ -203,7 +203,6 @@ public final class WizardryEventHandler {
// Find the angle between the direction the mob is looking and the direction the player is in
// Angle between a and b = acos((a.b) / (|a|*|b|))
double angle = Math.acos(vec.dotProduct(event.getEntity().getLookVec()) / vec.length());
System.out.println(angle);
// If the player is not within the 144-degree arc in front of the mob, it won't detect them
if(angle > 0.4 * Math.PI){
((EntityLiving)event.getEntityLiving()).setAttackTarget(null);
@@ -269,7 +268,7 @@ public final class WizardryEventHandler {
// Fireskin
if(event.getEntityLiving().isPotionActive(WizardryPotions.fireskin)
&& !MagicDamage.isEntityImmune(DamageType.FIRE, event.getEntityLiving()))
attacker.setFire(Spells.fire_breath.getProperty(Spell.BURN_DURATION).intValue());
attacker.setFire(Spells.fire_breath.getProperty(Spell.BURN_DURATION).intValue() * 20);
// Ice Shroud
if(event.getEntityLiving().isPotionActive(WizardryPotions.ice_shroud)
@@ -307,7 +306,7 @@ public final class WizardryEventHandler {
PotionEffect effect = event.getEntityLiving().getActivePotionEffect(WizardryPotions.ward);
if(effect != null && event.getSource().isMagicDamage()){
event.setAmount(event.getAmount() * Math.max(0, 1 - 0.4f * effect.getAmplifier())); // Resistance is 20%
event.setAmount(event.getAmount() * Math.max(0, 1 - 0.2f * (1 + effect.getAmplifier()))); // Resistance is 20%
}
// Flaming and freezing swords
@@ -491,4 +490,4 @@ public final class WizardryEventHandler {
}
}
}
}
@@ -1,6 +1,7 @@
package electroblob.wizardry.client;
import electroblob.wizardry.CommonProxy;
import electroblob.wizardry.Settings;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.block.BlockBookshelf;
import electroblob.wizardry.client.animation.ActionAnimation;
@@ -19,6 +20,7 @@ import electroblob.wizardry.client.model.ModelSageArmour;
import electroblob.wizardry.client.model.ModelWizardArmour;
import electroblob.wizardry.client.particle.*;
import electroblob.wizardry.client.particle.ParticleWizardry.IWizardryParticleFactory;
import electroblob.wizardry.client.renderer.RenderSpectralGolem;
import electroblob.wizardry.client.renderer.entity.*;
import electroblob.wizardry.client.renderer.entity.layers.*;
import electroblob.wizardry.client.renderer.overlay.RenderBlinkEffect;
@@ -164,7 +166,8 @@ public class ClientProxy extends CommonProxy {
IResourceManager manager = Minecraft.getMinecraft().getResourceManager();
if(manager instanceof IReloadableResourceManager){
((IReloadableResourceManager)manager).registerReloadListener(GuiSpellDisplay::loadSkins);
((IReloadableResourceManager)manager).registerReloadListener(GuiWizardHandbook::loadHandbookFile);
if (Wizardry.settings.loadHandbook)
((IReloadableResourceManager)manager).registerReloadListener(GuiWizardHandbook::loadHandbookFile);
}
}
@@ -728,6 +731,9 @@ public class ClientProxy extends CommonProxy {
LayerTiledOverlay.initialiseLayers(LayerMindControl::new);
LayerTiledOverlay.initialiseLayers(LayerSummonAnimation::new);
LayerTiledOverlay.initialiseLayers(LayerDisintegrateAnimation::new);
LayerTiledOverlay.initialiseLayers(LayerOak::new);
LayerTiledOverlay.initialiseLayers(LayerIron::new);
LayerTiledOverlay.initialiseLayers(LayerDiamond::new);
}
@Override
@@ -766,6 +772,7 @@ public class ClientProxy extends CommonProxy {
RenderingRegistry.registerEntityRenderingHandler(EntityIceGiant.class, RenderIceGiant::new);
RenderingRegistry.registerEntityRenderingHandler(EntityPhoenix.class, RenderPhoenix::new);
RenderingRegistry.registerEntityRenderingHandler(EntitySpectralGolem.class, RenderSpectralGolem::new);
// Projectiles
RenderingRegistry.registerEntityRenderingHandler(EntityMagicMissile.class, manager -> new RenderMagicArrow(manager,
@@ -780,6 +787,7 @@ public class ClientProxy extends CommonProxy {
new ResourceLocation(Wizardry.MODID, "textures/entity/ice_lance.png"), false, 16.0, 3.0, 22, 5, false));
RenderingRegistry.registerEntityRenderingHandler(EntityFlamecatcherArrow.class, manager -> new RenderMagicArrow(manager,
new ResourceLocation(Wizardry.MODID, "textures/entity/flamecatcher_arrow.png"), false, 8, 2.0, 16, 5, true));
RenderingRegistry.registerEntityRenderingHandler(EntityConjuredArrow.class, RenderConjuredArrow::new);
RenderingRegistry.registerEntityRenderingHandler(EntityForceArrow.class, RenderForceArrow::new);
@@ -151,7 +151,7 @@ class Contents {
int x = GuiWizardHandbook.isRightPage(startPage) ? left + GuiWizardHandbook.GUI_WIDTH - GuiWizardHandbook.TEXT_INSET_X - GuiWizardHandbook.PAGE_WIDTH : left + GuiWizardHandbook.TEXT_INSET_X;
int y = top + GuiWizardHandbook.TEXT_INSET_Y + startLine * font.FONT_HEIGHT;
list.add(new GuiButtonHyperlink.Internal(0, x, y, font, entry.title, entry, 0, "", maxLineNumber-startLine, GuiWizardHandbook.isRightPage(startPage)));
list.add(new GuiButtonHyperlink.Internal(0, x, y, font, entry.title, entry, 0, "", maxLineNumber-startLine, GuiWizardHandbook.isRightPage(startPage), false));
startLine++;
@@ -28,15 +28,17 @@ public abstract class GuiButtonHyperlink extends GuiButton {
final List<String> lines;
final int linesLeft;
GuiButtonHyperlink(int id, int x, int y, FontRenderer font, String text, int indent, String suffix, int linesLeft, boolean rightPage){
GuiButtonHyperlink(int id, int x, int y, FontRenderer font, String text, int indent, String suffix, int linesLeft, boolean rightPage, boolean spaceless){
super(id, x, y, font.getStringWidth(text), font.FONT_HEIGHT, text);
// Sometimes a link has punctuation or something after it that causes it to wrap onto a new line
String linkWithSuffix = text + suffix;
// If the string won't fit any words at the end of the current line, treat it as if we started a new line
if(font.getStringWidth(linkWithSuffix.split("\\s")[0]) > GuiWizardHandbook.PAGE_WIDTH - indent){
// If the string won't fit any words (or characters in a spaceless language) at the end of the current line,
// treat it as if we started a new line
String firstWord = spaceless ? linkWithSuffix.substring(0, 1) : linkWithSuffix.split("\\s")[0];
if(font.getStringWidth(firstWord) > GuiWizardHandbook.PAGE_WIDTH - indent){
indent = 0;
this.y += font.FONT_HEIGHT;
}
@@ -149,7 +151,7 @@ public abstract class GuiButtonHyperlink extends GuiButton {
* @throws IllegalArgumentException if the given argument array is empty or contains more than 2 arguments
* @throws JsonSyntaxException if the specified link target is not a URL or a valid section ID
*/
public static GuiButtonHyperlink create(int x, int y, FontRenderer font, List<String> upToLink, String[] arguments, String suffix, int linesLeft, boolean rightPage){
public static GuiButtonHyperlink create(int x, int y, FontRenderer font, List<String> upToLink, String[] arguments, String suffix, int linesLeft, boolean rightPage, boolean spaceless){
if(arguments.length == 0 || arguments.length > 2) throw new IllegalArgumentException("Incorrect array length!");
@@ -158,7 +160,7 @@ public abstract class GuiButtonHyperlink extends GuiButton {
if(arguments[0].matches(URL_REGEX)){
button = new GuiButtonHyperlink.External(0, x, y, font, arguments[arguments.length - 1], arguments[0],
font.getStringWidth(upToLink.get(upToLink.size() - 1)), suffix, linesLeft, rightPage);
font.getStringWidth(upToLink.get(upToLink.size() - 1)), suffix, linesLeft, rightPage, spaceless);
}else{
@@ -167,7 +169,7 @@ public abstract class GuiButtonHyperlink extends GuiButton {
if(target == null) throw new JsonSyntaxException("Hyperlink points to nonexistent section id " + arguments[0]);
button = new GuiButtonHyperlink.Internal(0, x, y, font, arguments[arguments.length - 1],
target, font.getStringWidth(upToLink.get(upToLink.size() - 1)), suffix, linesLeft, rightPage);
target, font.getStringWidth(upToLink.get(upToLink.size() - 1)), suffix, linesLeft, rightPage, spaceless);
}
return button;
@@ -177,8 +179,8 @@ public abstract class GuiButtonHyperlink extends GuiButton {
final Section target;
Internal(int id, int x, int y, FontRenderer font, String text, Section target, int indent, String suffix, int linesLeft, boolean rightPage){
super(id, x, y, font, text, indent, suffix, linesLeft, rightPage);
Internal(int id, int x, int y, FontRenderer font, String text, Section target, int indent, String suffix, int linesLeft, boolean rightPage, boolean spaceless){
super(id, x, y, font, text, indent, suffix, linesLeft, rightPage, spaceless);
this.target = target;
}
@@ -216,8 +218,8 @@ public abstract class GuiButtonHyperlink extends GuiButton {
final ITextComponent link;
External(int id, int x, int y, FontRenderer font, String text, String url, int indent, String suffix, int linesLeft, boolean rightPage){
super(id, x, y, font, text, indent, suffix, linesLeft, rightPage);
External(int id, int x, int y, FontRenderer font, String text, String url, int indent, String suffix, int linesLeft, boolean rightPage, boolean spaceless){
super(id, x, y, font, text, indent, suffix, linesLeft, rightPage, spaceless);
this.link = new TextComponentString(text);
link.getStyle().setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, url)).setColor(TextFormatting.DARK_BLUE);
}
@@ -496,24 +496,30 @@ public class GuiWizardHandbook extends GuiScreen {
Section currentSection = null;
for(Section section : sections.values()){
// We always want this button to do something, and taking the right-hand page means it always does
if(section.containsPage(doubleToSinglePage(currentPage, true))){
currentSection = section;
break;
if(currentPage < singleToDoublePage(pageCount)){
// Find current section
for(Section section : sections.values()){
// Take the right-hand page if going to the next section, and the left-hand page otherwise
if(section.containsPage(doubleToSinglePage(currentPage, button == nextSection))){
currentSection = section;
break;
}
}
}
if(currentSection != null){
List<Section> visibleSections = new ArrayList<>(sectionList);
visibleSections.removeIf(s -> !s.isUnlocked());
List<Section> visibleSections = new ArrayList<>(sectionList);
visibleSections.removeIf(s -> !s.isUnlocked());
int index = currentSection == null ? visibleSections.size() : visibleSections.indexOf(currentSection);
int index = visibleSections.indexOf(currentSection);
if(button == nextSection && index + 1 < visibleSections.size()){
if(button == nextSection){
if(index + 1 < visibleSections.size()){
currentPage = singleToDoublePage(visibleSections.get(index + 1).startPage);
}else if(index > 0){
}else{
currentPage = singleToDoublePage(pageCount);
}
}else{
if(index > 0){
currentPage = singleToDoublePage(visibleSections.get(index - 1).startPage);
}
}
@@ -1,5 +1,6 @@
package electroblob.wizardry.client.gui.handbook;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Streams;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
@@ -35,6 +36,8 @@ import java.util.*;
// be a non-static inner class
class Section {
private static final Set<String> SPACELESS_LANGUAGES = ImmutableSet.of("zh_cn", "zh_tw");
// Final fields are mandatory (none here though), the rest are optional
String title;
private String[] rawText;
@@ -293,7 +296,11 @@ class Section {
String linkRaw = paragraph.substring(linkStart, linkEnd + 1);
String[] arguments = paragraph.substring(linkStart + 1, linkEnd).split("\\s", 2);
String suffix = paragraph.substring(linkEnd).split("\\s", 2)[0].substring(1); // substring(1) to remove the @
String suffix = "";
// Account for trailing punctuation, except in languages that don't use spaces such as Chinese
boolean spaceless = SPACELESS_LANGUAGES.contains(Minecraft.getMinecraft().getLanguageManager().getCurrentLanguage().getLanguageCode());
if(!spaceless) paragraph.substring(linkEnd).split("\\s", 2)[0].substring(1); // substring(1) to remove the @
// The index of the single page currently being formatted, relative to the section
int pageRelative = (lines.size() + upToLink.size() - 1) / maxLineNumber;
@@ -311,7 +318,7 @@ class Section {
}
// The button id only does what you use it for, so we're just not using it at all.
this.buttons.get(pageRelative).add(GuiButtonHyperlink.create(x, y, font, upToLink, arguments, suffix, maxLineNumber - lineNumber - 1, GuiWizardHandbook.isRightPage(page)));
this.buttons.get(pageRelative).add(GuiButtonHyperlink.create(x, y, font, upToLink, arguments, suffix, maxLineNumber - lineNumber - 1, GuiWizardHandbook.isRightPage(page), spaceless));
// The link button should exactly overlay the display text in the main string
// If the link has no display text specified, it displays the unformatted target string
@@ -13,17 +13,17 @@ import net.minecraftforge.client.model.IModel;
import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.common.model.IModelState;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.*;
import java.util.function.Function;
public class ModelBookshelf implements IModel {
private static final ResourceLocation DEFAULT_BOOK_TEXTURE = new ResourceLocation(Wizardry.MODID, "blocks/books");
//private static final ResourceLocation DEFAULT_BOOK_TEXTURE = new ResourceLocation(Wizardry.MODID, "blocks/books");
private static final List<ResourceLocation> bookModelLocations = new ArrayList<>();
private static final Map<String, IBakedModel[][]> bakedBookModels = new HashMap<>();
private final ModelResourceLocation bookshelfModelLocation;
private final String variant;
@@ -49,19 +49,7 @@ public class ModelBookshelf implements IModel {
// I don't know why default state works here (surely it ought to be the state param?), but it works so who cares
IBakedModel bookshelf = bookshelfModel.bake(bookshelfModel.getDefaultState(), format, bakedTextureGetter);
ImmutableList<ResourceLocation> textures = BlockBookshelf.getBookTextures();
IBakedModel[][] books = new IBakedModel[textures.size()][BlockBookshelf.SLOT_COUNT];
for(int i = 0; i < textures.size(); i++){
ImmutableMap<String, String> retexturer = ImmutableMap.of("books", textures.get(i).toString());
for(int j = 0; j < BlockBookshelf.SLOT_COUNT; j++){
IModel bookModel = ModelLoaderRegistry.getModel(new ModelResourceLocation(bookModelLocations.get(j), variant)).retexture(retexturer);
books[i][j] = bookModel.bake(bookModel.getDefaultState(), format, bakedTextureGetter); // Same here!
}
}
IBakedModel[][] books = getBakedBookModels(format, bakedTextureGetter);
// To clarify: the whole point of doing this was to avoid having to bake 4 * 2^12 models per bookshelf type
// Therefore we have to have a baked bookshelf model that's kind of dynamic
@@ -74,6 +62,29 @@ public class ModelBookshelf implements IModel {
}
/** Retrieves the baked book models, or bakes them if they haven't been created yet. */
protected IBakedModel[][] getBakedBookModels(VertexFormat format, Function<ResourceLocation, TextureAtlasSprite> bakedTextureGetter) throws Exception{
if(bakedBookModels.get(variant) == null){
ImmutableList<ResourceLocation> textures = BlockBookshelf.getBookTextures();
bakedBookModels.put(variant, new IBakedModel[textures.size()][BlockBookshelf.SLOT_COUNT]);
for(int i = 0; i < textures.size(); i++){
ImmutableMap<String, String> retexturer = ImmutableMap.of("books", textures.get(i).toString());
for(int j = 0; j < BlockBookshelf.SLOT_COUNT; j++){
IModel bookModel = ModelLoaderRegistry.getModel(new ModelResourceLocation(bookModelLocations.get(j), variant)).retexture(retexturer);
bakedBookModels.get(variant)[i][j] = bookModel.bake(bookModel.getDefaultState(), format, bakedTextureGetter); // Same here!
}
}
}
return bakedBookModels.get(variant);
}
@Override
public Collection<ResourceLocation> getDependencies(){
return bookModelLocations;
@@ -0,0 +1,52 @@
package electroblob.wizardry.client.renderer;
import electroblob.wizardry.Wizardry;
import net.minecraft.client.model.ModelIronGolem;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.entity.RenderLiving;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.entity.monster.EntityIronGolem;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import org.lwjgl.opengl.GL11;
@SideOnly(Side.CLIENT)
public class RenderSpectralGolem extends RenderLiving<EntityIronGolem>
{
private static final ResourceLocation SPECTRAL_GOLEM_TEXTURES = new ResourceLocation(Wizardry.MODID, "textures/entity/spectral_golem.png");
public RenderSpectralGolem(RenderManager renderManagerIn)
{
super(renderManagerIn, new ModelIronGolem(), 0.5F);
}
/**
* Returns the location of an entity's texture. Doesn't seem to be called unless you call Render.bindEntityTexture.
*/
protected ResourceLocation getEntityTexture(EntityIronGolem entity)
{
return SPECTRAL_GOLEM_TEXTURES;
}
@Override
protected void preRenderCallback(EntityIronGolem entity, float partialTickTime){
super.preRenderCallback(entity, partialTickTime);
GlStateManager.enableBlend();
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GlStateManager.color(1, 1, 1, 0.7f);
}
protected void applyRotations(EntityIronGolem entityLiving, float ageInTicks, float rotationYaw, float partialTicks)
{
super.applyRotations(entityLiving, ageInTicks, rotationYaw, partialTicks);
if ((double)entityLiving.limbSwingAmount >= 0.01D)
{
float f = 13.0F;
float f1 = entityLiving.limbSwing - entityLiving.limbSwingAmount * (1.0F - partialTicks) + 6.0F;
float f2 = (Math.abs(f1 % 13.0F - 6.5F) - 3.25F) / 3.25F;
GlStateManager.rotate(6.5F * f2, 0.0F, 0.0F, 1.0F);
}
}
}
@@ -0,0 +1,37 @@
package electroblob.wizardry.client.renderer.entity;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.entity.projectile.EntityConjuredArrow;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.entity.RenderArrow;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import org.lwjgl.opengl.GL11;
@SideOnly(Side.CLIENT)
public class RenderConjuredArrow extends RenderArrow<EntityConjuredArrow> {
public static final ResourceLocation CONJURED_ARROW_TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/entity/conjured_arrow.png");
public RenderConjuredArrow(RenderManager manager) {
super(manager);
}
@Override
protected ResourceLocation getEntityTexture(EntityConjuredArrow entity) {
return CONJURED_ARROW_TEXTURE;
}
@Override
public void doRender(EntityConjuredArrow entity, double x, double y, double z, float entityYaw, float partialTicks) {
GlStateManager.pushMatrix();
GlStateManager.enableBlend();
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GlStateManager.color(1, 1, 1, 0.4f);
super.doRender(entity, x, y, z, entityYaw, partialTicks);
GlStateManager.popMatrix();
}
}
@@ -0,0 +1,53 @@
package electroblob.wizardry.client.renderer.entity.layers;
import electroblob.wizardry.registry.WizardryPotions;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.GlStateManager.DestFactor;
import net.minecraft.client.renderer.GlStateManager.SourceFactor;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.entity.RenderLivingBase;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.ResourceLocation;
/**
* Layer used to render the diamondflesh texture on creatures with the diamondflesh effect.
*
* @author WinDanesz
* @since Wizardry 4.3.7
*/
public class LayerDiamond extends LayerTiledOverlay<EntityLivingBase> {
private static final ResourceLocation TEXTURE = new ResourceLocation("textures/blocks/diamond_block.png");
public LayerDiamond(RenderLivingBase<?> renderer){
super(renderer);
}
@Override
public boolean shouldRender(EntityLivingBase entity, float partialTicks){
return !entity.isInvisible() && entity.isPotionActive(WizardryPotions.diamondflesh);
}
@Override
public ResourceLocation getTexture(EntityLivingBase entity, float partialTicks){
return TEXTURE;
}
@Override
public void doRenderLayer(EntityLivingBase entity, float limbSwing, float limbSwingAmount, float partialTicks,
float ageInTicks, float netHeadYaw, float headPitch, float scale){
GlStateManager.enableBlend();
GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA);
int j = entity.getBrightnessForRender();
int k = j % 65536;
int l = j / 65536;
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, (float) k, (float) l);
super.doRenderLayer(entity, limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw, headPitch, scale);
GlStateManager.disableBlend();
}
}
@@ -0,0 +1,53 @@
package electroblob.wizardry.client.renderer.entity.layers;
import electroblob.wizardry.registry.WizardryPotions;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.GlStateManager.DestFactor;
import net.minecraft.client.renderer.GlStateManager.SourceFactor;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.entity.RenderLivingBase;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.ResourceLocation;
/**
* Layer used to render the ironflesh texture on creatures with the ironflesh effect.
*
* @author WinDanesz
* @since Wizardry 4.3.7
*/
public class LayerIron extends LayerTiledOverlay<EntityLivingBase> {
private static final ResourceLocation TEXTURE = new ResourceLocation("textures/blocks/iron_block.png");
public LayerIron(RenderLivingBase<?> renderer){
super(renderer);
}
@Override
public boolean shouldRender(EntityLivingBase entity, float partialTicks){
return !entity.isInvisible() && entity.isPotionActive(WizardryPotions.ironflesh);
}
@Override
public ResourceLocation getTexture(EntityLivingBase entity, float partialTicks){
return TEXTURE;
}
@Override
public void doRenderLayer(EntityLivingBase entity, float limbSwing, float limbSwingAmount, float partialTicks,
float ageInTicks, float netHeadYaw, float headPitch, float scale){
GlStateManager.enableBlend();
GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA);
int j = entity.getBrightnessForRender();
int k = j % 65536;
int l = j / 65536;
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, (float) k, (float) l);
super.doRenderLayer(entity, limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw, headPitch, scale);
GlStateManager.disableBlend();
}
}
@@ -0,0 +1,53 @@
package electroblob.wizardry.client.renderer.entity.layers;
import electroblob.wizardry.registry.WizardryPotions;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.GlStateManager.DestFactor;
import net.minecraft.client.renderer.GlStateManager.SourceFactor;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.entity.RenderLivingBase;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.ResourceLocation;
/**
* Layer used to render the oakflesh texture on creatures with the oakflesh effect.
*
* @author WinDanesz
* @since Wizardry 4.3.7
*/
public class LayerOak extends LayerTiledOverlay<EntityLivingBase> {
private static final ResourceLocation TEXTURE = new ResourceLocation("textures/blocks/log_oak.png");
public LayerOak(RenderLivingBase<?> renderer){
super(renderer);
}
@Override
public boolean shouldRender(EntityLivingBase entity, float partialTicks){
return !entity.isInvisible() && entity.isPotionActive(WizardryPotions.oakflesh);
}
@Override
public ResourceLocation getTexture(EntityLivingBase entity, float partialTicks){
return TEXTURE;
}
@Override
public void doRenderLayer(EntityLivingBase entity, float limbSwing, float limbSwingAmount, float partialTicks,
float ageInTicks, float netHeadYaw, float headPitch, float scale){
GlStateManager.enableBlend();
GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA);
int j = entity.getBrightnessForRender();
int k = j % 65536;
int l = j / 65536;
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, (float) k, (float) l);
super.doRenderLayer(entity, limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw, headPitch, scale);
GlStateManager.disableBlend();
}
}
@@ -1,5 +1,6 @@
package electroblob.wizardry.constants;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.WizardryEventHandler;
/** Stores various global constants used in Wizardry. */
@@ -17,17 +18,17 @@ public final class Constants {
/** The bonus amount of wand upgrades that can be applied to a non-elemental wand. */
public static final int NON_ELEMENTAL_UPGRADE_BONUS = 3;
/** The fraction by which cooldowns are reduced for each level of cooldown upgrade. */
public static final float COOLDOWN_REDUCTION_PER_LEVEL = 0.15f;
public static float COOLDOWN_REDUCTION_PER_LEVEL = 0.15f;
/** The fraction by which maximum charge is increased for each level of storage upgrade. */
public static final float STORAGE_INCREASE_PER_LEVEL = 0.15f;
/** The fraction by which potency is increased for each tier of matching wand. */
public static final float POTENCY_INCREASE_PER_TIER = 0.15f;
public static float POTENCY_INCREASE_PER_TIER = 0.15f;
/** The fraction by which spell duration is increased for each level of duration upgrade. */
public static final float DURATION_INCREASE_PER_LEVEL = 0.25f;
public static float DURATION_INCREASE_PER_LEVEL = 0.25f;
/** The fraction by which spell range is increased for each level of range upgrade. */
public static final float RANGE_INCREASE_PER_LEVEL = 0.25f;
public static float RANGE_INCREASE_PER_LEVEL = 0.25f;
/** The fraction by which spell blast radius is increased for each level of range upgrade. */
public static final float BLAST_RADIUS_INCREASE_PER_LEVEL = 0.25f;
public static float BLAST_RADIUS_INCREASE_PER_LEVEL = 0.25f;
/** The fraction by which movement speed is reduced per level of frost effect. */
public static final double FROST_SLOWNESS_PER_LEVEL = 0.5;
/** The fraction by which movement speed is reduced per level of decay effect. */
@@ -46,7 +47,15 @@ public final class Constants {
* won't spawn again if something is already standing in it.
*/
public static final int DECAY_SPREAD_INTERVAL = 8;
/** The fraction by which potency is increased per level of the empowerment effect. */
public static final float EMPOWERMENT_POTENCY_PER_LEVEL = 0.25f;
// making this as an update to the existing values to not break addons directly relying on the fields
static {
POTENCY_INCREASE_PER_TIER = (float) Wizardry.settings.potencyIncreasePerTier;
COOLDOWN_REDUCTION_PER_LEVEL = (float) Wizardry.settings.cooldownReductionPerLevel;
DURATION_INCREASE_PER_LEVEL = (float) Wizardry.settings.durationIncreasePerLevel;
RANGE_INCREASE_PER_LEVEL = (float) Wizardry.settings.rangeIncreasePerLevel;
BLAST_RADIUS_INCREASE_PER_LEVEL = (float) Wizardry.settings.blastIncreasePerLevel;
RANGE_INCREASE_PER_LEVEL = (float) Wizardry.settings.frostSlownessIncreasePerLevel;
}
}
@@ -382,6 +382,7 @@ public class WizardData implements INBTSerializable<NBTTagCompound> {
activeImbuements.add((Imbuement)enchantment);
}else{
// Otherwise, removes the enchantment from the item
((Imbuement) enchantment).onImbuementRemoval(stack);
iterator.remove(); // FIXME: Apparently this can cause a CME
}
}
@@ -33,7 +33,7 @@ import java.util.Iterator;
* than having to deal with each of them separately, which would be inefficient and cumbersome (the former of those
* classes cannot extend the latter because they both need to extend different subclasses of
* {@link net.minecraft.enchantment.Enchantment}).
*
*
* @since Wizardry 1.2
*/
@Mod.EventBusSubscriber
@@ -69,12 +69,16 @@ public interface Imbuement {
Enchantment enchantment = Enchantment.getEnchantmentByID(enchantmentTag.getShort("id"));
// If the item contains a magic weapon enchantment, remove it from the item
if(enchantment instanceof Imbuement){
((Imbuement) enchantment).onImbuementRemoval(stack);
enchantmentIt.remove();
}
}
}
}
/** Allows executing some custom logic before this imbuement is being removed from the stack. Called when the imbuement is about to be removed. */
default void onImbuementRemoval(ItemStack stack){}
@SubscribeEvent
public static void onPlayerOpenContainerEvent(PlayerContainerEvent event){
// Brute-force fix to stop enchanted books in dungeon chests from having imbuements on them.
@@ -1,10 +1,8 @@
package electroblob.wizardry.entity.construct;
import electroblob.wizardry.entity.projectile.EntityConjuredArrow;
import electroblob.wizardry.registry.Spells;
import electroblob.wizardry.spell.Spell;
import net.minecraft.entity.projectile.EntityTippedArrow;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.World;
@@ -30,7 +28,7 @@ public class EntityArrowRain extends EntityScaledConstruct {
double y = posY + world.rand.nextDouble() * (double)height;
double z = posZ + (world.rand.nextDouble() - 0.5D) * (double)width;
EntityTippedArrow arrow = new EntityTippedArrow(world, x, y, z);
EntityConjuredArrow arrow = new EntityConjuredArrow(world, x, y, z);
arrow.motionX = MathHelper.cos((float)Math.toRadians(this.rotationYaw + 90));
arrow.motionY = -0.6;
@@ -38,7 +36,6 @@ public class EntityArrowRain extends EntityScaledConstruct {
arrow.shootingEntity = this.getCaster();
arrow.setDamage(7.0d * damageMultiplier);
arrow.setPotionEffect(new ItemStack(Items.ARROW));
this.world.spawnEntity(arrow);
}
@@ -32,7 +32,7 @@ public class EntityFireRing extends EntityScaledConstruct {
super.onUpdate();
if(!this.world.isRemote){
if(this.ticksExisted % 5 == 0 && !this.world.isRemote){
List<EntityLivingBase> targets = EntityUtils.getLivingWithinRadius(width/2, this.posX, this.posY, this.posZ, this.world);
@@ -168,6 +168,10 @@ public class EntityForcefield extends EntityMagicConstruct implements ICustomHit
((EntityPlayerMP)target).connection.sendPacket(new SPacketEntityVelocity(target));
}
if (this.ticksExisted % 5 == 0) {
this.lifetime = (int) (lifetime * 0.99);
}
}else{
Vec3d relativeImpactPos = targetRelativePos.normalize().scale(radius);
@@ -68,13 +68,15 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity
/** Data parameter for the wizard's element. */
private static final DataParameter<Integer> ELEMENT = EntityDataManager.createKey(EntityEvilWizard.class,
DataSerializers.VARINT);
/** Data parameters for the wizard's current continuous spell. */
private static final DataParameter<String> CONTINUOUS_SPELL = EntityDataManager.createKey(EntityEvilWizard.class, DataSerializers.STRING);
private static final DataParameter<Integer> SPELL_COUNTER = EntityDataManager.createKey(EntityEvilWizard.class, DataSerializers.VARINT);
/** The resource location for the evil wizard's loot table. */
private static final ResourceLocation LOOT_TABLE = new ResourceLocation(Wizardry.MODID, "entities/evil_wizard");
// Field implementations
private List<Spell> spells = new ArrayList<Spell>(4);
private Spell continuousSpell;
private int spellCounter;
public EntityEvilWizard(World world){
@@ -93,6 +95,8 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity
super.entityInit();
this.dataManager.register(HEAL_COOLDOWN, -1);
this.dataManager.register(ELEMENT, -1);
this.dataManager.register(CONTINUOUS_SPELL, "ebwizardry:none");
this.dataManager.register(SPELL_COUNTER, 0);
}
@Override
@@ -168,23 +172,23 @@ public class EntityEvilWizard extends EntityMob implements ISpellCaster, IEntity
}
@Override
public void setContinuousSpell(Spell spell){
this.continuousSpell = spell;
public void setContinuousSpell(Spell spell) {
this.dataManager.set(CONTINUOUS_SPELL, spell.getRegistryName().toString());
}
@Override
public Spell getContinuousSpell(){
return this.continuousSpell;
public Spell getContinuousSpell() {
return Spell.get(this.dataManager.get(CONTINUOUS_SPELL));
}
@Override
public void setSpellCounter(int count){
spellCounter = count;
public void setSpellCounter(int count) {
this.dataManager.set(SPELL_COUNTER, count);
}
@Override
public int getSpellCounter(){
return spellCounter;
public int getSpellCounter() {
return this.dataManager.get(SPELL_COUNTER);
}
@Override
@@ -52,7 +52,7 @@ public class EntityMagicSlime extends EntitySlime implements ISummonedCreature {
super(world);
this.setPosition(target.posX, target.posY, target.posZ);
this.startRiding(target);
this.setOwnerId(caster.getUniqueID());
if (caster != null) this.setOwnerId(caster.getUniqueID());
this.setSlimeSize(2, false); // Needs to be called before setting the experience value to 0
this.experienceValue = 0;
this.lifetime = lifetime;
@@ -0,0 +1,192 @@
package electroblob.wizardry.entity.living;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.util.ParticleBuilder;
import net.minecraft.entity.EntityFlying;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.ai.EntityAIAttackMelee;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAILookAtVillager;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAIMoveThroughVillage;
import net.minecraft.entity.ai.EntityAIMoveTowardsRestriction;
import net.minecraft.entity.ai.EntityAIMoveTowardsTarget;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAIWanderAvoidWater;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.monster.EntityIronGolem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.datasync.DataParameter;
import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.network.datasync.EntityDataManager;
import net.minecraft.util.EnumHand;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.EnumDifficulty;
import net.minecraft.world.World;
import java.util.UUID;
public class EntitySpectralGolem extends EntityIronGolem implements ISummonedCreature {
private static final DataParameter<Boolean> SPAWN_PARTICLES = EntityDataManager.createKey(EntitySpectralGolem.class, DataSerializers.BOOLEAN);
// Field implementations
private int lifetime = -1;
private UUID casterUUID;
// Setter + getter implementations
@Override public int getLifetime(){ return lifetime; }
@Override public void setLifetime(int lifetime){ this.lifetime = lifetime; }
@Override public UUID getOwnerId(){ return casterUUID; }
@Override public void setOwnerId(UUID uuid){ this.casterUUID = uuid; }
/** Creates a new golem minion in the given world. */
public EntitySpectralGolem(World world){
super(world);
this.experienceValue = 0;
}
@Override
protected void entityInit(){
super.entityInit();
this.dataManager.register(SPAWN_PARTICLES, true);
}
@Override
protected void initEntityAI() {
this.tasks.addTask(1, new EntityAIAttackMelee(this, 1.0D, true));
this.tasks.addTask(2, new EntityAIMoveTowardsTarget(this, 0.9D, 32.0F));
this.tasks.addTask(3, new EntityAIMoveThroughVillage(this, 0.6D, true));
this.tasks.addTask(4, new EntityAIMoveTowardsRestriction(this, 1.0D));
this.tasks.addTask(5, new EntityAILookAtVillager(this));
this.tasks.addTask(6, new EntityAIWanderAvoidWater(this, 0.6D));
this.tasks.addTask(7, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F));
this.tasks.addTask(8, new EntityAILookIdle(this));
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false));
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget<>(this, EntityLivingBase.class,
0, false, true, this.getTargetSelector()));
}
@Override protected void setEquipmentBasedOnDifficulty(DifficultyInstance difficulty){} // They don't have equipment!
// Implementations
@Override
public void setRevengeTarget(EntityLivingBase entity){
if(this.shouldRevengeTarget(entity)) super.setRevengeTarget(entity);
}
@Override
public void onUpdate(){
super.onUpdate();
this.updateDelegate();
// Adds a dust particle effect
if(this.world.isRemote){
double x = this.posX - this.width / 2 + this.rand.nextFloat() * width;
double y = this.posY + this.height * this.rand.nextFloat() + 0.2f;
double z = this.posZ - this.width / 2 + this.rand.nextFloat() * width;
ParticleBuilder.create(ParticleBuilder.Type.DUST).pos(x, y, z).clr(0.7f, 0.9f, 1).shaded(true).spawn(world);
}
}
@Override
public void onSpawn(){
if(this.dataManager.get(SPAWN_PARTICLES)) this.spawnParticleEffect();
}
@Override
public void onDespawn(){
this.spawnParticleEffect();
}
private void spawnParticleEffect(){
if(this.world.isRemote){
for(int i = 0; i < 15; i++){
this.world.spawnParticle(EnumParticleTypes.SMOKE_LARGE, this.posX + this.rand.nextFloat() - 0.5f,
this.posY + this.rand.nextFloat() * 2, this.posZ + this.rand.nextFloat() - 0.5f, 0, 0, 0);
}
}
}
@Override
public boolean hasParticleEffect(){
return true;
}
@Override
public boolean hasAnimation(){
return this.dataManager.get(SPAWN_PARTICLES) || this.ticksExisted > 20;
}
public void hideParticles(){
this.dataManager.set(SPAWN_PARTICLES, false);
}
@Override
protected boolean processInteract(EntityPlayer player, EnumHand hand){
// In this case, the delegate method determines whether super is called.
// Rather handily, we can make use of Java's short-circuiting method of evaluating OR statements.
return this.interactDelegate(player, hand) || super.processInteract(player, hand);
}
@Override
public void writeEntityToNBT(NBTTagCompound nbttagcompound){
super.writeEntityToNBT(nbttagcompound);
this.writeNBTDelegate(nbttagcompound);
}
@Override
public void readEntityFromNBT(NBTTagCompound nbttagcompound){
super.readEntityFromNBT(nbttagcompound);
this.readNBTDelegate(nbttagcompound);
}
// Recommended overrides
@Override protected int getExperiencePoints(EntityPlayer player){ return 0; }
@Override protected boolean canDropLoot(){ return false; }
@Override protected Item getDropItem(){ return null; }
@Override protected ResourceLocation getLootTable(){ return null; }
@Override public boolean canPickUpLoot(){ return false; }
// This vanilla method has nothing to do with the custom despawn() method.
@Override protected boolean canDespawn(){
return getCaster() == null && getOwnerId() == null;
}
@Override
public boolean getCanSpawnHere(){
return this.world.getDifficulty() != EnumDifficulty.PEACEFUL;
}
@Override
public boolean canAttackClass(Class<? extends EntityLivingBase> entityType){
// Returns true unless the given entity type is a flying entity.
return !EntityFlying.class.isAssignableFrom(entityType);
}
@Override
public ITextComponent getDisplayName(){
if(getCaster() != null){
return new TextComponentTranslation(NAMEPLATE_TRANSLATION_KEY, getCaster().getName(),
new TextComponentTranslation("entity." + this.getEntityString() + ".name"));
}else{
return super.getDisplayName();
}
}
@Override
public boolean hasCustomName(){
// If this returns true, the renderer will show the nameplate when looking directly at the entity
return Wizardry.settings.summonedCreatureNames && getCaster() != null;
}
}
@@ -47,6 +47,7 @@ import net.minecraftforge.common.util.FakePlayer;
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.ForgeRegistries;
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@@ -81,11 +82,12 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
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);
/** Data parameters for the wizard's current continuous spell. */
private static final DataParameter<String> CONTINUOUS_SPELL = EntityDataManager.createKey(EntityWizard.class, DataSerializers.STRING);
private static final DataParameter<Integer> SPELL_COUNTER = EntityDataManager.createKey(EntityWizard.class, DataSerializers.VARINT);
// Field implementations
private List<Spell> spells = new ArrayList<Spell>(4);
private Spell continuousSpell;
private int spellCounter;
/** A set of the positions of the blocks that are part of this wizard's tower. */
private Set<BlockPos> towerBlocks;
@@ -102,6 +104,8 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
super.entityInit();
this.dataManager.register(HEAL_COOLDOWN, -1);
this.dataManager.register(ELEMENT, 0);
this.dataManager.register(CONTINUOUS_SPELL, "ebwizardry:none");
this.dataManager.register(SPELL_COUNTER, 0);
}
@Override
@@ -182,23 +186,23 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
}
@Override
public void setContinuousSpell(Spell spell){
this.continuousSpell = spell;
public void setContinuousSpell(Spell spell) {
this.dataManager.set(CONTINUOUS_SPELL, spell.getRegistryName().toString());
}
@Override
public Spell getContinuousSpell(){
return this.continuousSpell;
public Spell getContinuousSpell() {
return Spell.get(this.dataManager.get(CONTINUOUS_SPELL));
}
@Override
public void setSpellCounter(int count){
spellCounter = count;
public void setSpellCounter(int count) {
this.dataManager.set(SPELL_COUNTER, count);
}
@Override
public int getSpellCounter(){
return spellCounter;
public int getSpellCounter() {
return this.dataManager.get(SPELL_COUNTER);
}
@Override
@@ -634,10 +638,9 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
if(this.getElement() != Element.MAGIC && rand.nextInt(4) > 0 && !specialismSpells.isEmpty()){
// This means it is more likely for spell books sold to be of the same element as the wizard if the
// wizard has an element.
return new ItemStack(WizardryItems.spell_book, 1,
specialismSpells.get(rand.nextInt(specialismSpells.size())).metadata());
return getBookStackForSpell(specialismSpells.get(rand.nextInt(specialismSpells.size())));
}else{
return new ItemStack(WizardryItems.spell_book, 1, spells.get(rand.nextInt(spells.size())).metadata());
return getBookStackForSpell(spells.get(rand.nextInt(spells.size())));
}
}else{
if(this.getElement() != Element.MAGIC && rand.nextInt(4) > 0){
@@ -656,10 +659,9 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
if(this.getElement() != Element.MAGIC && rand.nextInt(4) > 0 && !specialismSpells.isEmpty()){
// This means it is more likely for spell books sold to be of the same element as the wizard if the
// wizard has an element.
return new ItemStack(WizardryItems.spell_book, 1,
specialismSpells.get(rand.nextInt(specialismSpells.size())).metadata());
return getBookStackForSpell(specialismSpells.get(rand.nextInt(specialismSpells.size())));
}else{
return new ItemStack(WizardryItems.spell_book, 1, spells.get(rand.nextInt(spells.size())).metadata());
return getBookStackForSpell(spells.get(rand.nextInt(spells.size())));
}
}else if(randomiser < 6){
if(this.getElement() != Element.MAGIC && rand.nextInt(4) > 0){
@@ -693,10 +695,9 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
if(this.getElement() != Element.MAGIC && rand.nextInt(4) > 0 && !specialismSpells.isEmpty()){
// This means it is more likely for spell books sold to be of the same element as the wizard if the
// wizard has an element.
return new ItemStack(WizardryItems.spell_book, 1,
specialismSpells.get(rand.nextInt(specialismSpells.size())).metadata());
return getBookStackForSpell(specialismSpells.get(rand.nextInt(specialismSpells.size())));
}else{
return new ItemStack(WizardryItems.spell_book, 1, spells.get(rand.nextInt(spells.size())).metadata());
return getBookStackForSpell(spells.get(rand.nextInt(spells.size())));
}
}else if(randomiser < 6){
if(this.getElement() != Element.MAGIC && rand.nextInt(4) > 0){
@@ -721,8 +722,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
if(randomiser < 5 && this.getElement() != Element.MAGIC && !specialismSpells.isEmpty()){
// Master spells can only be sold by a specialist in that element.
return new ItemStack(WizardryItems.spell_book, 1,
specialismSpells.get(rand.nextInt(specialismSpells.size())).metadata());
return getBookStackForSpell(specialismSpells.get(rand.nextInt(specialismSpells.size())));
}else if(randomiser < 6){
if(this.getElement() != Element.MAGIC && rand.nextInt(4) > 0){
@@ -798,7 +798,6 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
Tier maxTier = Tier.NOVICE;
List<Spell> npcSpells = Spell.getSpells(s -> s.canBeCastBy(wizard, false));
npcSpells.removeIf(s -> !s.applicableForItem(WizardryItems.spell_book));
for(int i = 0; i < n; i++){
@@ -846,6 +845,22 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
return maxTier;
}
/**
* Helper method to handle addon spell books.
* @param spell the spell to look up.
* @return Checks all items of the spell's namespace (modid) if they are applicable for the spell and returns the first match, or falls back to WizardryItems.spell_book if no match was found.
*/
public static ItemStack getBookStackForSpell(Spell spell) {
String modid = spell.getRegistryName().getNamespace();
if (modid.equals(Wizardry.MODID)) {
return new ItemStack(WizardryItems.spell_book, 1, spell.metadata());
}
Optional<Item> firstMatch = ForgeRegistries.ITEMS.getValuesCollection().stream().filter(v -> v instanceof ItemSpellBook && spell.applicableForItem(v)
&& v.getRegistryName().getNamespace().equals(modid)).findFirst();
return firstMatch.map(item -> new ItemStack(item, 1, spell.metadata())).orElseGet(() -> new ItemStack(WizardryItems.spell_book, 1, spell.metadata()));
}
@Override
public void writeSpawnData(ByteBuf data){
data.writeInt(textureIndex);
@@ -0,0 +1,34 @@
package electroblob.wizardry.entity.projectile;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
public class EntityConjuredArrow extends EntityArrow {
public EntityConjuredArrow(World worldIn) {
super(worldIn);
}
public EntityConjuredArrow(World worldIn, double x, double y, double z) {
super(worldIn, x, y, z);
}
public EntityConjuredArrow(World worldIn, EntityLivingBase shooter) {
super(worldIn, shooter);
}
@Override
public void onUpdate() {
super.onUpdate();
if (this.timeInGround > 400) {
this.setDead();
}
}
@Override
protected ItemStack getArrowStack() {
return ItemStack.EMPTY;
}
}
@@ -0,0 +1,45 @@
package electroblob.wizardry.event;
import electroblob.wizardry.item.ItemArtefact;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
import net.minecraftforge.fml.common.eventhandler.Event;
/**
* SpellBindEvent is fired when a check happens for an ItemArtefact using {@link electroblob.wizardry.item.ItemArtefact#isArtefactActive(net.minecraft.entity.player.EntityPlayer, net.minecraft.item.Item)}
* <i>Fired on both sides.</i><br>
* <br>
* This event is {@link Cancelable}. <br>
* <br>
* This event has a result. {@link HasResult}. Set the result to Result.ALLOW to consider an artefact "active"<br>
* <br>
* This event is fired on the {@link MinecraftForge#EVENT_BUS}.
*
* @author WinDanesz
* @since Wizardry 4.3.10
*/
@Cancelable
@Event.HasResult
public class ArtefactCheckEvent extends PlayerEvent {
ItemArtefact artefact;
EntityPlayer player;
public ArtefactCheckEvent(EntityPlayer player, ItemArtefact artefact) {
super(player);
this.player = player;
this.artefact = artefact;
setResult(Result.DENY);
}
public ItemArtefact getArtefact() {
return artefact;
}
public EntityPlayer getPlayer() {
return player;
}
}
@@ -0,0 +1,56 @@
package electroblob.wizardry.event;
import electroblob.wizardry.constants.Element;
import electroblob.wizardry.tileentity.TileEntityImbuementAltar;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
import net.minecraftforge.fml.common.eventhandler.Event;
/**
* ImbuementActivateEvent is fired when {@link TileEntityImbuementAltar#getImbuementResult(net.minecraft.item.ItemStack, electroblob.wizardry.constants.Element[],
* boolean, net.minecraft.world.World, net.minecraft.entity.player.EntityPlayer)} is called to allow adding in imbuement "recipes" dynamically, based on the
* contents of the Imbuement altar's receptacles and the item placed on the altar.
*
* <i>Note that this event is only fired on the server side.</i><br>
* <br>
* To alter the result of the imbuement process, change the {@link electroblob.wizardry.event.ImbuementActivateEvent#result} result of the process.<br>
* <br>
* This event is {@link Cancelable}. If this event is canceled, no further processing takes place.<br>
* <br>
* This event does not have a result. {@link Event.HasResult}<br>
* <br>
* This event is fired on the {@link MinecraftForge#EVENT_BUS}.
*
* @author WinDanesz
* @since Wizardry 4.3.5
*/
@Cancelable
public class ImbuementActivateEvent extends Event {
/** The item stack being imbued */
public ItemStack input;
/** The elements of the four receptacles */
public Element[] receptacleElements;
/** A reference to the current world object (may be null if {@code fullLootGen} is false) */
public World world;
/** The player that last interacted with the imbuement altar, or null if there isn't one (or if this is being queried for other reasons, e.g. JEI) */
public EntityPlayer lastUser;
/** The resulting item stack of the imbuement process */
public ItemStack result;
public ImbuementActivateEvent(ItemStack input, Element[] receptacleElements, World world, EntityPlayer lastUser, ItemStack result) {
super();
this.input = input;
this.receptacleElements = receptacleElements;
this.world = world;
this.lastUser = lastUser;
this.result = result;
}
}
@@ -0,0 +1,37 @@
package electroblob.wizardry.event;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
/**
* ResurrectionEvent is fired when a player is about to be resurrected, after all other checks have been performed.
* <i>Note that this event is only fired on the server side.</i><br>
* <br>
* This event is {@link Cancelable}. If this event is canceled, the player is not resurrected.<br>
* <br>
* This event does not have a result. {@link HasResult}<br>
* <br>
* This event is fired on the {@link MinecraftForge#EVENT_BUS}.
*
* @author Electroblob
* @since Wizardry 2.1
*/
@Cancelable
public class ResurrectionEvent extends PlayerEvent {
private final EntityPlayer caster;
public ResurrectionEvent(EntityPlayer player, EntityPlayer caster){
super(player);
this.caster = caster;
}
/** Returns the player that cast the resurrection spell. If the player resurrected themselves, this will be the
* same as {@link ResurrectionEvent#getEntityPlayer()}. */
public EntityPlayer getCaster(){
return caster;
}
}
@@ -46,6 +46,10 @@ public final class WizardryBaublesIntegration {
ARTEFACT_TYPE_MAP.put(ItemArtefact.Type.RING, BaubleType.RING);
ARTEFACT_TYPE_MAP.put(ItemArtefact.Type.AMULET, BaubleType.AMULET);
ARTEFACT_TYPE_MAP.put(ItemArtefact.Type.CHARM, BaubleType.CHARM);
ARTEFACT_TYPE_MAP.put(ItemArtefact.Type.BELT, BaubleType.BELT);
ARTEFACT_TYPE_MAP.put(ItemArtefact.Type.BODY, BaubleType.BODY);
ARTEFACT_TYPE_MAP.put(ItemArtefact.Type.HEAD, BaubleType.HEAD);
ARTEFACT_TYPE_MAP.put(ItemArtefact.Type.TRINKET, BaubleType.TRINKET);
}
public static boolean enabled(){
@@ -10,6 +10,7 @@ import electroblob.wizardry.entity.living.ISummonedCreature;
import electroblob.wizardry.entity.projectile.EntityDart;
import electroblob.wizardry.entity.projectile.EntityForceOrb;
import electroblob.wizardry.entity.projectile.EntityIceShard;
import electroblob.wizardry.event.ArtefactCheckEvent;
import electroblob.wizardry.event.SpellCastEvent;
import electroblob.wizardry.event.SpellCastEvent.Source;
import electroblob.wizardry.integration.DamageSafetyChecker;
@@ -37,6 +38,7 @@ import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World;
import net.minecraft.world.biome.Biome;
import net.minecraftforge.common.BiomeDictionary;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.event.entity.living.LivingDeathEvent;
import net.minecraftforge.event.entity.living.LivingEvent;
@@ -88,7 +90,11 @@ public class ItemArtefact extends Item {
/** An artefact that improves attacking spells. Two of these can be active at any one time. */ RING(2),
/** An artefact that improves defensive spells. One of these can be active at any one time. */ AMULET(1),
/** An artefact that improves utility spells. One of these can be active at any one time. */ CHARM(1);
/** An artefact that improves utility spells. One of these can be active at any one time. */ CHARM(1),
/** Added for add-on artefacts. */ BELT(1),
/** Added for add-on artefacts. */ BODY(1),
/** Added for add-on artefacts. */ HEAD(1),
/** Added for add-on artefacts. */ TRINKET(1);
public final int maxAtOnce;
@@ -123,6 +129,8 @@ public class ItemArtefact extends Item {
this.enabled = enabled;
}
public boolean isEnabled() { return enabled; }
@Override
public EnumRarity getRarity(ItemStack stack){
return rarity;
@@ -176,6 +184,13 @@ public class ItemArtefact extends Item {
if(!((ItemArtefact)artefact).enabled) return false; // Disabled in the config
ArtefactCheckEvent event = new ArtefactCheckEvent(player, (ItemArtefact) artefact);
if(MinecraftForge.EVENT_BUS.post(event)) return false;
if (event.getResult() == Event.Result.ALLOW) {
return true;
}
if(WizardryBaublesIntegration.enabled()){
return WizardryBaublesIntegration.isBaubleEquipped(player, artefact);
}else{
@@ -344,6 +359,8 @@ public class ItemArtefact extends Item {
findMatchingWandAndExecute(player, Spells.shield, wand -> {
if(wand.getItem() instanceof ItemScroll) return; // Ignore scrolls since they shouldn't work
List<Entity> projectiles = EntityUtils.getEntitiesWithinRadius(5, player.posX, player.posY, player.posZ, world, Entity.class);
projectiles.removeIf(e -> !(e instanceof IProjectile));
Vec3d look = player.getLookVec();
@@ -765,6 +782,7 @@ public class ItemArtefact extends Item {
&& Streams.stream(player.getHeldEquipment()).anyMatch(s -> s.getItem() instanceof ISpellCastingItem
&& ((ISpellCastingItem)s.getItem()).getCurrentSpell(s).getElement() == Element.NECROMANCY))){
event.getEntityLiving().addPotionEffect(new PotionEffect(WizardryPotions.curse_of_soulbinding, 400));
CurseOfSoulbinding.getSoulboundCreatures(WizardData.get(player)).add(event.getEntity().getUniqueID());
}
@@ -15,9 +15,16 @@ import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.Slot;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.*;
import net.minecraft.util.ActionResult;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumHand;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.Style;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@@ -100,6 +107,13 @@ public class ItemScroll extends Item implements ISpellCastingItem, IWorkbenchIte
tooltip.add(spell.getElement().getDisplayName());
tooltip.add(spell.getType().getDisplayName());
}
// Advanced tooltips displays the source mod's name if the spell is not from Wizardry
if (advanced.isAdvanced() && this.getRegistryName().toString().equals(Wizardry.MODID + ":scroll") && !spell.getRegistryName().getNamespace().equals(Wizardry.MODID)) {
String modId = spell.getRegistryName().getNamespace();
String name = new Style().setColor(TextFormatting.BLUE).setItalic(true).getFormattingCode() +
Loader.instance().getIndexedModList().get(modId).getMetadata().name;
tooltip.add(name);
}
}
}
@@ -195,7 +209,7 @@ public class ItemScroll extends Item implements ISpellCastingItem, IWorkbenchIte
if(!spell.isContinuous && !caster.isCreative()) stack.shrink(1);
// Now uses the vanilla cooldown mechanic to prevent spamming of spells
if(!spell.isContinuous) caster.getCooldownTracker().setCooldown(this, spell.getCooldown());
if(!spell.isContinuous && !caster.isCreative()) caster.getCooldownTracker().setCooldown(this, spell.getCooldown());
}
return true;
@@ -230,7 +244,7 @@ public class ItemScroll extends Item implements ISpellCastingItem, IWorkbenchIte
MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Finish(Source.SCROLL, spell, user, modifiers, castingTick));
spell.finishCasting(user.world, user, Double.NaN, Double.NaN, Double.NaN, null, castingTick, modifiers);
if(user instanceof EntityPlayer){
if(user instanceof EntityPlayer && !((EntityPlayer)user).isCreative()){
((EntityPlayer)user).getCooldownTracker().setCooldown(this, spell.getCooldown());
}
}
@@ -1,6 +1,7 @@
package electroblob.wizardry.item;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.entity.projectile.EntityConjuredArrow;
import electroblob.wizardry.registry.Spells;
import electroblob.wizardry.util.InventoryUtils;
import net.minecraft.enchantment.EnchantmentHelper;
@@ -14,6 +15,7 @@ import net.minecraft.init.SoundEvents;
import net.minecraft.item.IItemPropertyGetter;
import net.minecraft.item.ItemArrow;
import net.minecraft.item.ItemBow;
import net.minecraft.item.ItemSpectralArrow;
import net.minecraft.item.ItemStack;
import net.minecraft.stats.StatList;
import net.minecraft.util.*;
@@ -197,8 +199,7 @@ public class ItemSpectralBow extends ItemBow implements IConjuredItem {
if(!world.isRemote){
ItemArrow itemarrow = (ItemArrow)Items.ARROW;
EntityArrow entityarrow = itemarrow.createArrow(world, new ItemStack(itemarrow), entityplayer);
EntityConjuredArrow entityarrow = new EntityConjuredArrow(world, entityplayer);
entityarrow.shoot(entityplayer, entityplayer.rotationPitch, entityplayer.rotationYaw, 0.0F,
f * 3.0F, 1.0F);
@@ -12,10 +12,15 @@ import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.*;
import net.minecraft.util.ActionResult;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumHand;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.Style;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.oredict.OreDictionary;
@@ -96,6 +101,13 @@ public class ItemSpellBook extends Item {
tooltip.add(spell.getElement().getDisplayName());
tooltip.add(spell.getType().getDisplayName());
}
// Advanced tooltips displays the source mod's name if the spell is not from Wizardry
if (advanced.isAdvanced() && this.getRegistryName().toString().equals(Wizardry.MODID + ":spell_book") && !spell.getRegistryName().getNamespace().equals(Wizardry.MODID)) {
String modId = spell.getRegistryName().getNamespace();
String name = new Style().setColor(TextFormatting.BLUE).setItalic(true).getFormattingCode() +
Loader.instance().getIndexedModList().get(modId).getMetadata().name;
tooltip.add(name);
}
}
}
@@ -226,9 +226,15 @@ public class ItemWand extends Item implements IWorkbenchItem, ISpellCastingItem,
}
@Override
public void onUpdate(ItemStack stack, World world, Entity entity, int slot, boolean isHeld){
public void onUpdate(ItemStack stack, World world, Entity entity, int slot, boolean isHeldInMainhand){
boolean isHeld = isHeldInMainhand || entity instanceof EntityLivingBase && ItemStack.areItemStacksEqual(stack, ((EntityLivingBase) entity).getHeldItemOffhand());
WandHelper.decrementCooldowns(stack);
// If Wizardry.settings.wandsMustBeHeldToDecrementCooldown is false, the cooldowns will be decremented.
// If Wizardry.settings.wandsMustBeHeldToDecrementCooldown is true and isHeld is true, the cooldowns will also be decremented.
// If Wizardry.settings.wandsMustBeHeldToDecrementCooldown is true and isHeld is false, the cooldowns will not be decremented.
if (!Wizardry.settings.wandsMustBeHeldToDecrementCooldown || isHeld) {
WandHelper.decrementCooldowns(stack);
}
// Decrements wand damage (increases mana) every 1.5 seconds if it has a condenser upgrade
if(!world.isRemote && !this.isManaFull(stack) && world.getTotalWorldTime() % Constants.CONDENSER_TICK_INTERVAL == 0){
@@ -849,7 +855,12 @@ public class ItemWand extends Item implements IWorkbenchItem, ISpellCastingItem,
int chargeDepleted = this.getManaCapacity(centre.getStack()) - this.getMana(centre.getStack());
int manaPerItem = Constants.MANA_PER_CRYSTAL;
// Not too pretty but allows addons implementing the IManaStoringItem interface to provide their mana amount for custom crystals,
// previously this was defaulted to the regular crystal's amount, allowing players to exploit it if a crystal was worth less mana than that.
int manaPerItem = crystals.getStack().getItem() instanceof IManaStoringItem ?
((IManaStoringItem) crystals.getStack().getItem()).getMana(crystals.getStack()) :
crystals.getStack().getItem() instanceof ItemCrystal ? Constants.MANA_PER_CRYSTAL : Constants.MANA_PER_SHARD;
if(crystals.getStack().getItem() == WizardryItems.crystal_shard) manaPerItem = Constants.MANA_PER_SHARD;
if(crystals.getStack().getItem() == WizardryItems.grand_crystal) manaPerItem = Constants.GRAND_CRYSTAL_MANA;
@@ -1,5 +1,7 @@
package electroblob.wizardry.item;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Streams;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.client.DrawingUtils;
@@ -44,7 +46,11 @@ import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nullable;
import java.util.*;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.Supplier;
@Mod.EventBusSubscriber
@@ -54,6 +60,28 @@ public class ItemWizardArmour extends ItemArmor implements IWorkbenchItem, IMana
private static final float SAGE_OTHER_COST_REDUCTION = 0.2f;
private static final float WARLOCK_SPEED_BOOST = 0.2f;
private static final UUID WARLOCK_SPEED_BOOST_UUID = UUID.fromString("4bad7152-2663-4b1b-bb59-552e92847031");
// Standard ItemArmor modifiers
private 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")};
@Override
public Multimap<String, AttributeModifier> getItemAttributeModifiers(EntityEquipmentSlot slot) {
// The vanilla armor handling logic from ItemArmor.getItemAttributeModifiers was moved to ItemWizardArmour.getAttributeModifiers to allow checking if the stack has enough mana
Multimap<String, AttributeModifier> multimap = ArrayListMultimap.create();
return multimap;
}
@Override
public Multimap<String, AttributeModifier> getAttributeModifiers(EntityEquipmentSlot slot, ItemStack stack) {
Multimap<String, AttributeModifier> multimap = super.getAttributeModifiers(slot, stack);
// only grant armor if the equipment has mana
if (slot == this.armorType && !((ItemWizardArmour) stack.getItem()).isManaEmpty(stack)) {
multimap.put(SharedMonsterAttributes.ARMOR.getName(), new AttributeModifier(ARMOR_MODIFIERS[slot.getIndex()], "Armor modifier", this.damageReduceAmount, 0));
multimap.put(SharedMonsterAttributes.ARMOR_TOUGHNESS.getName(), new AttributeModifier(ARMOR_MODIFIERS[slot.getIndex()], "Armor toughness", this.toughness, 0));
}
return multimap;
}
public enum ArmourClass {
@@ -181,8 +209,8 @@ public class ItemWizardArmour extends ItemArmor implements IWorkbenchItem, IMana
@Override
public void onArmorTick(World world, EntityPlayer player, ItemStack itemStack){
if(armorType == EntityEquipmentSlot.HEAD && isWearingFullSet(player, element, ArmourClass.BATTLEMAGE)
&& player.ticksExisted % 20 == 0){
if(armorType == EntityEquipmentSlot.HEAD && player.ticksExisted % 20 == 0
&& isWearingFullSet(player, element, ArmourClass.BATTLEMAGE) && doAllArmourPiecesHaveMana(player)){
player.addPotionEffect(new PotionEffect(WizardryPotions.ward, 219, 0, true, false));
}
}
@@ -209,7 +237,7 @@ public class ItemWizardArmour extends ItemArmor implements IWorkbenchItem, IMana
modifiers.set(WizardryItems.cooldown_upgrade, modifiers.get(WizardryItems.cooldown_upgrade) - armourClass.cooldownReduction, true);
// Full set bonuses
if(this.armorType == EntityEquipmentSlot.HEAD && isWearingFullSet(caster, element, armourClass)){
if(this.armorType == EntityEquipmentSlot.HEAD && isWearingFullSet(caster, element, armourClass) && doAllArmourPiecesHaveMana(caster)){
if(armourClass == ArmourClass.SAGE && spell.getElement() != this.element){
modifiers.set(SpellModifiers.COST, 1 - SAGE_OTHER_COST_REDUCTION, false);
}
@@ -306,7 +334,12 @@ public class ItemWizardArmour extends ItemArmor implements IWorkbenchItem, IMana
int chargeDepleted = this.getManaCapacity(centre.getStack()) - this.getMana(centre.getStack());
int manaPerItem = Constants.MANA_PER_CRYSTAL;
// Not too pretty but allows addons implementing the IManaStoringItem interface to provide their mana amount for custom crystals,
// previously this was defaulted to the regular crystal's amount, allowing players to exploit it if a crystal was worth less mana than that.
int manaPerItem = crystals.getStack().getItem() instanceof IManaStoringItem ?
((IManaStoringItem) crystals.getStack().getItem()).getMana(crystals.getStack()) :
crystals.getStack().getItem() instanceof ItemCrystal ? Constants.MANA_PER_CRYSTAL : Constants.MANA_PER_SHARD;
if(crystals.getStack().getItem() == WizardryItems.crystal_shard) manaPerItem = Constants.MANA_PER_SHARD;
if(crystals.getStack().getItem() == WizardryItems.grand_crystal) manaPerItem = Constants.GRAND_CRYSTAL_MANA;
@@ -335,7 +368,7 @@ public class ItemWizardArmour extends ItemArmor implements IWorkbenchItem, IMana
IAttributeInstance movementSpeed = event.getEntityLiving().getAttributeMap().getAttributeInstance(SharedMonsterAttributes.MOVEMENT_SPEED);
if(isWearingFullSet(event.getEntityLiving(), null, ArmourClass.WARLOCK)){
if(isWearingFullSet(event.getEntityLiving(), null, ArmourClass.WARLOCK) && doAllArmourPiecesHaveMana(event.getEntityLiving())){
// Only apply the modifier once (can't just check this is the helmet since it might not be the last piece equipped)
if(movementSpeed.getModifier(WARLOCK_SPEED_BOOST_UUID) == null){
movementSpeed.applyModifier(new AttributeModifier(WARLOCK_SPEED_BOOST_UUID, "Warlock set bonus", WARLOCK_SPEED_BOOST, Operations.MULTIPLY_FLAT));
@@ -405,7 +438,7 @@ public class ItemWizardArmour extends ItemArmor implements IWorkbenchItem, IMana
* @param armourClass The class to check, or null to accept any class as long as they are all the same.
* @return True if the entity is wearing a full set of the given element and class, false otherwise.
*/
private static boolean isWearingFullSet(EntityLivingBase entity, @Nullable Element element, @Nullable ArmourClass armourClass){
public static boolean isWearingFullSet(EntityLivingBase entity, @Nullable Element element, @Nullable ArmourClass armourClass){
ItemStack helmet = entity.getItemStackFromSlot(EntityEquipmentSlot.HEAD);
if(!(helmet.getItem() instanceof ItemWizardArmour)) return false;
Element e = element == null ? ((ItemWizardArmour)helmet.getItem()).element : element;
@@ -416,6 +449,16 @@ public class ItemWizardArmour extends ItemArmor implements IWorkbenchItem, IMana
&& ((ItemWizardArmour)entity.getItemStackFromSlot(s).getItem()).armourClass == ac);
}
/**
* Returns whether the given entity's armour pieces which implement {@link IManaStoringItem} has mana. Ignores pieces which doesn't have a mana storage.
* @param entity The entity to query.
* @return True if all armour pieces which implement {@link IManaStoringItem} has mana, false otherwise.
*/
public static boolean doAllArmourPiecesHaveMana(EntityLivingBase entity){
return Arrays.stream(InventoryUtils.ARMOUR_SLOTS).noneMatch(s -> entity.getItemStackFromSlot(s).getItem() instanceof IManaStoringItem
&& ((IManaStoringItem) entity.getItemStackFromSlot(s).getItem()).isManaEmpty(entity.getItemStackFromSlot(s)));
}
@SubscribeEvent
public static void onLivingSetAttackTargetEvent(LivingSetAttackTargetEvent event){
// Undo the mob detection penalty for wearing armour when invisible
@@ -10,6 +10,7 @@ import net.minecraft.util.ActionResult;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumHand;
import net.minecraft.util.text.Style;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World;
@@ -36,7 +37,11 @@ public class ItemWizardHandbook extends Item {
@Override
public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand){
ItemStack stack = player.getHeldItem(hand);
player.openGui(Wizardry.instance, WizardryGuiHandler.WIZARD_HANDBOOK, world, 0, 0, 0);
if (Wizardry.settings.loadHandbook) {
player.openGui(Wizardry.instance, WizardryGuiHandler.WIZARD_HANDBOOK, world, 0, 0, 0);
} else if (!world.isRemote){
player.sendStatusMessage(new TextComponentTranslation("item." + Wizardry.MODID + ":wizard_handbook.disabled"), false);
}
return ActionResult.newResult(EnumActionResult.SUCCESS, stack);
}
@@ -12,12 +12,15 @@ import electroblob.wizardry.entity.living.*;
import electroblob.wizardry.entity.projectile.EntityFirebomb;
import electroblob.wizardry.entity.projectile.EntityMagicFireball;
import electroblob.wizardry.event.SpellCastEvent;
import electroblob.wizardry.event.SpellCastEvent.Source;
import electroblob.wizardry.item.IManaStoringItem;
import electroblob.wizardry.item.ISpellCastingItem;
import electroblob.wizardry.item.ItemArtefact;
import electroblob.wizardry.registry.*;
import electroblob.wizardry.spell.Banish;
import electroblob.wizardry.spell.Spell;
import electroblob.wizardry.util.BlockUtils;
import electroblob.wizardry.util.EntityUtils;
import electroblob.wizardry.util.SpellModifiers;
import electroblob.wizardry.util.SpellProperties.Context;
import net.minecraft.entity.effect.EntityLightningBolt;
import net.minecraft.entity.item.EntityFallingBlock;
@@ -174,6 +177,23 @@ public abstract class Forfeit {
forfeit.apply(event.getWorld(), player);
ItemStack stack = player.getHeldItemMainhand();
if(!(stack.getItem() instanceof ISpellCastingItem)){
stack = player.getHeldItemOffhand();
if(!(stack.getItem() instanceof ISpellCastingItem)) stack = ItemStack.EMPTY;
}
if(!stack.isEmpty()){
// Still need to charge the player mana or consume the scroll
if(event.getSource() == Source.SCROLL){
if(!player.isCreative()) stack.shrink(1);
}else if(stack.getItem() instanceof IManaStoringItem){
int cost = (int)(event.getSpell().getCost() * event.getModifiers().get(SpellModifiers.COST) + 0.1f); // Weird floaty rounding
((IManaStoringItem)stack.getItem()).consumeMana(stack, cost, player);
}
}
WizardryAdvancementTriggers.spell_failure.triggerFor(player);
EntityUtils.playSoundAtPlayer(player, forfeit.getSound(), WizardrySounds.SPELLS, 1, 1);
@@ -222,10 +242,11 @@ public abstract class Forfeit {
}));
add(Tier.MASTER, Element.FIRE, create("burn_surroundings", (w, p) -> {
if(!w.isRemote){
if(!w.isRemote && EntityUtils.canDamageBlocks(p, w)){
List<BlockPos> sphere = BlockUtils.getBlockSphere(p.getPosition(), 6);
for(BlockPos pos : sphere){
if(w.rand.nextBoolean() && w.isAirBlock(pos)) w.setBlockState(pos, Blocks.FIRE.getDefaultState());
if(w.rand.nextBoolean() && w.isAirBlock(pos) && BlockUtils.canPlaceBlock(p, w, pos))
w.setBlockState(pos, Blocks.FIRE.getDefaultState());
}
}
}));
@@ -376,10 +397,11 @@ public abstract class Forfeit {
}));
add(Tier.NOVICE, Element.EARTH, create("snares", (w, p) -> {
if(!w.isRemote){
if(!w.isRemote && EntityUtils.canDamageBlocks(p, w)){
for(EnumFacing direction : EnumFacing.HORIZONTALS){
BlockPos pos = p.getPosition().offset(direction);
if(BlockUtils.canBlockBeReplaced(w, pos)) w.setBlockState(pos, WizardryBlocks.snare.getDefaultState());
if(BlockUtils.canBlockBeReplaced(w, pos) && BlockUtils.canPlaceBlock(p, w, pos))
w.setBlockState(pos, WizardryBlocks.snare.getDefaultState());
}
}
}));
@@ -393,9 +415,9 @@ public abstract class Forfeit {
}));
add(Tier.APPRENTICE, Element.EARTH, create("uproot_plants", (w, p) -> {
if(!w.isRemote){
if(!w.isRemote && EntityUtils.canDamageBlocks(p, w)){
List<BlockPos> sphere = BlockUtils.getBlockSphere(p.getPosition(), 5);
sphere.removeIf(pos -> !(w.getBlockState(pos).getBlock() instanceof IPlantable));
sphere.removeIf(pos -> !(w.getBlockState(pos).getBlock() instanceof IPlantable) || !BlockUtils.canBreakBlock(p, w, pos));
sphere.forEach(pos -> w.destroyBlock(pos, true));
}
}));
@@ -403,9 +425,9 @@ public abstract class Forfeit {
add(Tier.APPRENTICE, Element.EARTH, create("poison_self", (w, p) -> p.addPotionEffect(new PotionEffect(MobEffects.POISON, 400, 1))));
add(Tier.ADVANCED, Element.EARTH, create("flood", (w, p) -> {
if(!w.isRemote){
if(!w.isRemote && EntityUtils.canDamageBlocks(p, w)){
List<BlockPos> sphere = BlockUtils.getBlockSphere(p.getPosition().up(), 2);
sphere.removeIf(pos -> !BlockUtils.canBlockBeReplaced(w, pos, true));
sphere.removeIf(pos -> !BlockUtils.canBlockBeReplaced(w, pos, true) || !BlockUtils.canPlaceBlock(p, w, pos));
sphere.forEach(pos -> w.setBlockState(pos, Blocks.WATER.getDefaultState()));
}
}));
@@ -413,8 +435,7 @@ public abstract class Forfeit {
add(Tier.MASTER, Element.EARTH, create("bury_self", (w, p) -> {
if(!w.isRemote){
List<BlockPos> sphere = BlockUtils.getBlockSphere(p.getPosition(), 4);
sphere.removeIf(pos -> !w.getBlockState(pos).isFullCube());
sphere.removeIf(pos -> BlockUtils.isBlockUnbreakable(w, pos));
sphere.removeIf(pos -> !w.getBlockState(pos).isFullCube() || BlockUtils.isBlockUnbreakable(w, pos) || BlockUtils.canBreakBlock(p, w, pos));
sphere.forEach(pos -> {
EntityFallingBlock block = new EntityFallingBlock(w, pos.getX() + 0.5, pos.getY() + 0.5,
pos.getZ() + 0.5, w.getBlockState(pos));
@@ -1,13 +1,13 @@
package electroblob.wizardry.misc;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.item.IManaStoringItem;
import electroblob.wizardry.item.ItemManaFlask;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.CraftingManager;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
@@ -15,6 +15,8 @@ import net.minecraftforge.fml.common.gameevent.PlayerEvent;
import net.minecraftforge.oredict.OreDictionary;
import net.minecraftforge.oredict.ShapelessOreRecipe;
import java.util.Collection;
/**
* Implements a dynamic crafting recipe for recharging items with mana flasks.
*
@@ -24,6 +26,8 @@ import net.minecraftforge.oredict.ShapelessOreRecipe;
@Mod.EventBusSubscriber
public class RecipeRechargeWithFlask extends ShapelessOreRecipe {
private static final Multimap<Item, RecipeRechargeWithFlask> FLASK_RECIPES = HashMultimap.create();
private final IManaStoringItem chargeable;
private final ItemManaFlask flask;
@@ -38,6 +42,7 @@ public class RecipeRechargeWithFlask extends ShapelessOreRecipe {
if(!(chargeable instanceof IManaStoringItem)) throw new IllegalArgumentException("Item to be charged must be an instance of IManaStoringItem");
this.chargeable = (IManaStoringItem)chargeable;
this.flask = flask;
FLASK_RECIPES.put(chargeable, this);
}
// Commented out for now because JEI spams the log with errors about the recipe having no output
@@ -91,11 +96,11 @@ public class RecipeRechargeWithFlask extends ShapelessOreRecipe {
// This means that although I no longer have to replace the result every tick, I still need to do it here
// ... I thought the whole point of the new recipe system was so that I DIDN'T have to do this?!
if(event.craftMatrix instanceof InventoryCrafting){
for(IRecipe recipe : CraftingManager.REGISTRY){
if(recipe instanceof RecipeRechargeWithFlask
&& recipe.matches((InventoryCrafting)event.craftMatrix, event.player.world)){
Collection<RecipeRechargeWithFlask> recipes = FLASK_RECIPES.get(event.crafting.getItem());
for(RecipeRechargeWithFlask recipe : recipes){
if(recipe.matches((InventoryCrafting)event.craftMatrix, event.player.world)){
// Have to modify the itemstack in the actual event, it cannot be replaced
((RecipeRechargeWithFlask)recipe).rechargeItemAndCopyNBT(event.crafting, (InventoryCrafting)event.craftMatrix);
recipe.rechargeItemAndCopyNBT(event.crafting, (InventoryCrafting)event.craftMatrix);
}
}
}
@@ -1,6 +1,7 @@
package electroblob.wizardry.packet;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.event.ResurrectionEvent;
import electroblob.wizardry.inventory.ContainerArcaneWorkbench;
import electroblob.wizardry.item.ISpellCastingItem;
import electroblob.wizardry.packet.PacketControlInput.Message;
@@ -13,6 +14,7 @@ import io.netty.buffer.ByteBuf;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumHand;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
@@ -79,6 +81,7 @@ public class PacketControlInput implements IMessageHandler<Message, IMessage> {
.filter(s -> Resurrection.canStackResurrect(s, player)).findFirst().orElse(null);
if(stack != null){
if(MinecraftForge.EVENT_BUS.post(new ResurrectionEvent(player, player))) break;
// This should suffice, since this is the only way a player can cast resurrection when dead!
((ISpellCastingItem)stack.getItem()).cast(stack, Spells.resurrection, player, EnumHand.MAIN_HAND, 0, new SpellModifiers());
break;
@@ -1,11 +1,14 @@
package electroblob.wizardry.potion;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.item.ItemWizardArmour;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.ItemStack;
import net.minecraft.util.DamageSource;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.common.ISpecialArmor;
public class CurseUndeath extends Curse {
@@ -25,7 +28,7 @@ public class CurseUndeath extends Curse {
// Adapted from EntityZombie
if(entitylivingbase.world.isDaytime() && !entitylivingbase.world.isRemote){
float f = entitylivingbase.getBrightness();
if(f > 0.5F && entitylivingbase.world.rand.nextFloat() * 30.0F < (f - 0.4F) * 2.0F
@@ -35,14 +38,21 @@ public class CurseUndeath extends Curse {
boolean flag = true;
ItemStack itemstack = entitylivingbase.getItemStackFromSlot(EntityEquipmentSlot.HEAD);
if(!itemstack.isEmpty()){
if(itemstack.isItemStackDamageable()){
if (!itemstack.isEmpty()) {
if (itemstack.isItemStackDamageable()) {
itemstack.setItemDamage(itemstack.getItemDamage() + entitylivingbase.world.rand.nextInt(2));
if(itemstack.getItemDamage() >= itemstack.getMaxDamage()){
entitylivingbase.renderBrokenItemStack(itemstack);
entitylivingbase.setItemStackToSlot(EntityEquipmentSlot.HEAD, ItemStack.EMPTY);
if (itemstack.getItem() instanceof ISpecialArmor) {
((ISpecialArmor) itemstack.getItem()).damageArmor(entitylivingbase, itemstack, DamageSource.ON_FIRE, entitylivingbase.world.rand.nextInt(2), EntityEquipmentSlot.HEAD.getSlotIndex());
} else {
itemstack.setItemDamage(itemstack.getItemDamage() + entitylivingbase.world.rand.nextInt(2));
if (itemstack.getItemDamage() >= itemstack.getMaxDamage()) {
if (itemstack.getItem() instanceof ItemWizardArmour) {
entitylivingbase.setFire(8);
} else {
entitylivingbase.renderBrokenItemStack(itemstack);
entitylivingbase.setItemStackToSlot(EntityEquipmentSlot.HEAD, ItemStack.EMPTY);
}
}
}
}
@@ -2,17 +2,14 @@ package electroblob.wizardry.potion;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.registry.WizardryPotions;
import electroblob.wizardry.registry.WizardrySounds;
import electroblob.wizardry.util.EntityUtils;
import electroblob.wizardry.util.GeometryUtils;
import electroblob.wizardry.util.NBTExtras;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.nbt.NBTUtil;
import net.minecraft.network.play.server.SPacketEntityVelocity;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent;
import net.minecraftforge.fml.common.Mod;
@@ -23,8 +20,6 @@ public class PotionContainment extends PotionMagicEffect {
public static final String ENTITY_TAG = "containmentPos";
private static final double RUBBERBAND_THRESHOLD = 0.24;
public PotionContainment(boolean isBadEffect, int liquidColour){
super(isBadEffect, liquidColour, new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icons/containment.png"));
this.setPotionName("potion." + Wizardry.MODID + ":containment");
@@ -41,7 +36,6 @@ public class PotionContainment extends PotionMagicEffect {
@Override
public void performEffect(EntityLivingBase target, int strength){
float maxDistance = getContainmentDistance(strength);
// Initialise the containment position to the entity's position if it wasn't set already
@@ -63,59 +57,14 @@ public class PotionContainment extends PotionMagicEffect {
if(target.getEntityBoundingBox().maxZ > origin.z + maxDistance) z = origin.z + maxDistance - target.width/2;
if(target.getEntityBoundingBox().minZ < origin.z - maxDistance) z = origin.z - maxDistance + target.width/2;
if(x != target.posX || y != target.posY || z != target.posZ){
// if(target.world.isRemote){
//
// if(x != target.posX){
// for(int i = 0; i < 20; i++){
// ParticleBuilder.create(ParticleBuilder.Type.DUST).pos(
// x,
// target.posY + target.height * target.world.rand.nextFloat(),
// target.posZ + target.width * (target.world.rand.nextFloat() - 0.5f))
// .face(EnumFacing.EAST).clr(0.8f, 0.9f, 1).spawn(target.world);
// }
// }
//
// if(y != target.posY){
// for(int i = 0; i < 20; i++){
// ParticleBuilder.create(ParticleBuilder.Type.DUST).pos(
// target.posX + target.width * (target.world.rand.nextFloat() - 0.5f),
// y,
// target.posZ + target.width * (target.world.rand.nextFloat() - 0.5f))
// .face(EnumFacing.UP).clr(0.8f, 0.9f, 1).spawn(target.world);
// }
// }
//
// if(z != target.posZ){
// for(int i = 0; i < 20; i++){
// ParticleBuilder.create(ParticleBuilder.Type.DUST).pos(
// target.posX + target.width * (target.world.rand.nextFloat() - 0.5f),
// target.posY + target.height * target.world.rand.nextFloat(),
// z)
// .face(EnumFacing.SOUTH).clr(0.8f, 0.9f, 1).spawn(target.world);
// }
// }
// }
// Rubberbanding prevention (the 0.25 limit is from NetHandlerPlayServer, just search "moved wrongly"
if(target instanceof EntityPlayer){
x = MathHelper.clamp(x, target.posX - RUBBERBAND_THRESHOLD, target.posX + RUBBERBAND_THRESHOLD);
y = MathHelper.clamp(y, target.posY - RUBBERBAND_THRESHOLD, target.posY + RUBBERBAND_THRESHOLD);
z = MathHelper.clamp(z, target.posZ - RUBBERBAND_THRESHOLD, target.posZ + RUBBERBAND_THRESHOLD);
}
if(x != target.posX || y != target.posY || z != target.posZ)
{
target.addVelocity(0.15 * Math.signum(x - target.posX), 0.15 * Math.signum(y - target.posY), 0.15 * Math.signum(z - target.posZ));
EntityUtils.undoGravity(target);
target.addVelocity(0.35 * Math.signum(x - target.posX), 0.35 * Math.signum(y - target.posY), 0.35 * Math.signum(z - target.posZ));
target.setPositionAndUpdate(x, y, z); // FIXME: This line must be causing the server rubberbanding, not sure why
// Player motion is handled on that player's client so needs packets
if(target instanceof EntityPlayerMP){
((EntityPlayerMP)target).connection.sendPacket(new SPacketEntityVelocity(target));
if(target.world.isRemote){
target.world.playSound(target.posX, target.posY, target.posZ, WizardrySounds.ENTITY_FORCEFIELD_DEFLECT,
WizardrySounds.SPELLS, 0.3f, 1f, false);
}
//
// target.world.playSound(target.posX, target.posY, target.posZ, WizardrySounds.ENTITY_FORCEFIELD_DEFLECT,
// WizardrySounds.SPELLS, 0.3f, 1f, false);
}
// Need to do this here because it's the only way to hook into potion ending both client- and server-side
@@ -0,0 +1,28 @@
package electroblob.wizardry.potion;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.util.EntityUtils;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber
public class PotionDiamondflesh extends PotionMagicEffect {
public PotionDiamondflesh(boolean isBadEffect, int liquidColour) {
super(isBadEffect, liquidColour, new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icons/diamondflesh.png"));
// This needs to be here because registerPotionAttributeModifier doesn't like it if the potion has no name yet.
this.setPotionName("potion." + Wizardry.MODID + ":ironflesh");
this.registerPotionAttributeModifier(SharedMonsterAttributes.MOVEMENT_SPEED,
"158a8af2-6db0-4340-a01c-a7b60d10ddf4", -0.1f, EntityUtils.Operations.MULTIPLY_CUMULATIVE);
this.registerPotionAttributeModifier(SharedMonsterAttributes.ARMOR_TOUGHNESS,
"a68d4532-5847-426c-9b03-d541b113cec2", 3.0f, EntityUtils.Operations.ADD);
this.registerPotionAttributeModifier(SharedMonsterAttributes.ARMOR,
"46a095be-82dd-43fd-8b67-13f51591eb8e", 4.0f, EntityUtils.Operations.ADD);
}
@Override
public boolean isReady(int duration, int amplifier) {
return true;
}
}
@@ -5,6 +5,7 @@ import electroblob.wizardry.constants.Constants;
import electroblob.wizardry.registry.WizardryPotions;
import electroblob.wizardry.util.ParticleBuilder;
import electroblob.wizardry.util.ParticleBuilder.Type;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
@@ -50,4 +51,18 @@ public class PotionFrost extends PotionMagicEffect implements ICustomPotionParti
}
}
@Override
public void performEffect(EntityLivingBase entitylivingbase, int strength) {
if (entitylivingbase.isBurning()) {
if (entitylivingbase.isPotionActive(WizardryPotions.frost)) {
entitylivingbase.removePotionEffect(WizardryPotions.frost);
entitylivingbase.extinguish();
}
}
}
@Override
public boolean isReady(int duration, int amplifier) {
return true;
}
}
@@ -0,0 +1,28 @@
package electroblob.wizardry.potion;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.util.EntityUtils;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber
public class PotionIronflesh extends PotionMagicEffect {
public PotionIronflesh(boolean isBadEffect, int liquidColour) {
super(isBadEffect, liquidColour, new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icons/ironflesh.png"));
// This needs to be here because registerPotionAttributeModifier doesn't like it if the potion has no name yet.
this.setPotionName("potion." + Wizardry.MODID + ":ironflesh");
this.registerPotionAttributeModifier(SharedMonsterAttributes.MOVEMENT_SPEED,
"fe607d55-50e3-4f4f-a959-6571503f92f4", -0.1f, EntityUtils.Operations.MULTIPLY_CUMULATIVE);
this.registerPotionAttributeModifier(SharedMonsterAttributes.KNOCKBACK_RESISTANCE,
"6f78206e-8dd4-4d44-9792-d7a882111951", 0.3f, EntityUtils.Operations.ADD);
this.registerPotionAttributeModifier(SharedMonsterAttributes.ARMOR,
"e1adff1e-8510-4a09-96ed-ef677cad20c1", 4.0f, EntityUtils.Operations.ADD);
}
@Override
public boolean isReady(int duration, int amplifier) {
return true;
}
}
@@ -0,0 +1,28 @@
package electroblob.wizardry.potion;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.util.EntityUtils;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber
public class PotionOakflesh extends PotionMagicEffect {
public PotionOakflesh(boolean isBadEffect, int liquidColour) {
super(isBadEffect, liquidColour, new ResourceLocation(Wizardry.MODID, "textures/gui/potion_icons/oakflesh.png"));
// This needs to be here because registerPotionAttributeModifier doesn't like it if the potion has no name yet.
this.setPotionName("potion." + Wizardry.MODID + ":ironflesh");
this.registerPotionAttributeModifier(SharedMonsterAttributes.MOVEMENT_SPEED,
"98b4ba66-7c50-4a4c-9f3f-40bcb37313b5", -0.1f, EntityUtils.Operations.MULTIPLY_CUMULATIVE);
this.registerPotionAttributeModifier(SharedMonsterAttributes.MAX_HEALTH,
"ed9d0423-60f4-4998-bd8d-dc7c33bd45b8", 0.2f, EntityUtils.Operations.MULTIPLY_FLAT);
this.registerPotionAttributeModifier(SharedMonsterAttributes.ARMOR,
"0b607c3f-fb14-43d7-96b5-1c1b6f6da242", 3.0f, EntityUtils.Operations.ADD);
}
@Override
public boolean isReady(int duration, int amplifier) {
return true;
}
}
@@ -359,7 +359,7 @@ public final class Spells {
registry.register(new GreaterHeal());
registry.register(new SpellConstruct<>("healing_aura", SpellActions.POINT_DOWN, EntityHealAura::new, false).addProperties(Spell.EFFECT_RADIUS, Spell.DAMAGE, Spell.HEALTH));
registry.register(new Forcefield());
registry.register(new SpellBuff("ironflesh", 0.4f, 0.5f, 0.6f, () -> MobEffects.RESISTANCE).soundValues(0.7f, 1.2f, 0.4f));
registry.register(new SpellBuff("ironflesh", 0.4f, 0.5f, 0.6f, () -> WizardryPotions.ironflesh).soundValues(0.7f, 1.2f, 0.4f));
registry.register(new Transience());
registry.register(new Meteor());
@@ -378,9 +378,10 @@ public final class Spells {
registry.register(new SpellMinion<>("silverfish_swarm", EntitySilverfishMinion::new).soundValues(1, 1.1f, 0.1f));
registry.register(new SpellConstructRanged<>("black_hole", EntityBlackHole::new, false).addProperties(Spell.EFFECT_RADIUS).soundValues(2, 0.7f, 0));
registry.register(new Shockwave());
registry.register(new SummonIronGolem());
registry.register(new SpellMinion<>("summon_iron_golem", EntitySpectralGolem::new).soundValues(1, 1.1f, 0.1f));
registry.register(new ArrowRain());
registry.register(new SpellBuff("diamondflesh", 0.1f, 0.7f, 1, () -> MobEffects.RESISTANCE).soundValues(0.7f, 1.2f, 0.4f));
registry.register(new SpellBuff("diamondflesh", 0.1f, 0.7f, 1, () -> WizardryPotions.diamondflesh).soundValues(0.7f, 1.2f, 0.4f));
registry.register(new SpellBuff("font_of_vitality", 1, 0.8f, 0.3f, () -> MobEffects.ABSORPTION, () -> MobEffects.REGENERATION).soundValues(0.7f, 1.2f, 0.4f));
// Wizardry 1.1 spells
@@ -398,7 +399,7 @@ public final class Spells {
registry.register(new PocketWorkbench());
registry.register(new ImbueWeapon());
registry.register(new InvigoratingPresence());
registry.register(new SpellBuff("oakflesh", 0.6f, 0.5f, 0.4f, () -> MobEffects.RESISTANCE).soundValues(0.7f, 1.2f, 0.4f));
registry.register(new SpellBuff("oakflesh", 0.6f, 0.5f, 0.4f, () -> WizardryPotions.oakflesh).soundValues(0.7f, 1.2f, 0.4f));
registry.register(new SpellProjectile<>("greater_fireball", EntityLargeMagicFireball::new).addProperties(Spell.DAMAGE, EntityLargeMagicFireball.EXPLOSION_POWER));//new GreaterFireball());
registry.register(new FlamingWeapon());
@@ -88,6 +88,7 @@ public class WizardryEntities {
registry.register(createEntry(EntitySpiritHorse.class, "spirit_horse", TrackingType.LIVING).egg(0x5464c6, 0xbcc2e8).build());
registry.register(createEntry(EntityPhoenix.class, "phoenix", TrackingType.LIVING).egg(0xff4900, 0xfde535).build());
registry.register(createEntry(EntityIceGiant.class, "ice_giant", TrackingType.LIVING).egg(0x5bacd9, 0xeffaff).build());
registry.register(createEntry(EntitySpectralGolem.class, "spectral_golem", TrackingType.LIVING).egg(0x5bacd9, 0xeffaff).build());
registry.register(createEntry(EntityMagicSlime.class, "magic_slime", TrackingType.LIVING).build());
registry.register(createEntry(EntityDecoy.class, "decoy", TrackingType.LIVING).build());
@@ -113,6 +114,7 @@ public class WizardryEntities {
registry.register(createEntry(EntityDart.class, "dart", TrackingType.PROJECTILE).build());
registry.register(createEntry(EntityIceLance.class, "ice_lance", TrackingType.PROJECTILE).build());
registry.register(createEntry(EntityFlamecatcherArrow.class, "flamecatcher_arrow", TrackingType.PROJECTILE).build());
registry.register(createEntry(EntityConjuredArrow.class, "conjured_arrow", TrackingType.PROJECTILE).build());
// Directionless projectiles
registry.register(createEntry(EntityFirebomb.class, "firebomb", TrackingType.PROJECTILE).build());
@@ -6,7 +6,11 @@ import electroblob.wizardry.loot.RandomSpell;
import electroblob.wizardry.loot.WizardSpell;
import net.minecraft.entity.EnumCreatureType;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.storage.loot.*;
import net.minecraft.world.storage.loot.LootEntry;
import net.minecraft.world.storage.loot.LootEntryTable;
import net.minecraft.world.storage.loot.LootPool;
import net.minecraft.world.storage.loot.LootTableList;
import net.minecraft.world.storage.loot.RandomValueRange;
import net.minecraft.world.storage.loot.conditions.LootCondition;
import net.minecraft.world.storage.loot.functions.LootFunctionManager;
import net.minecraftforge.event.LootTableLoadEvent;
@@ -90,23 +94,27 @@ public final class WizardryLoot {
event.getTable().addPool(getAdditive(Wizardry.MODID + ":chests/jungle_dispenser_additions", Wizardry.MODID + "_additional_dispenser_loot"));
}
// Mob drops
// Let's hope mods will play nice and store their entity loot tables under 'entities' or 'entity'
// If not, packmakers will have to sort it out themselves using the whitelist/blacklist
if(Arrays.asList(Wizardry.settings.mobLootTableWhitelist).contains(event.getName())){
event.getTable().addPool(getAdditive(Wizardry.MODID + ":entities/mob_additions", Wizardry.MODID + "_additional_mob_drops"));
}else if(!Arrays.asList(Wizardry.settings.mobLootTableBlacklist).contains(event.getName())
&& event.getName().getPath().contains("entities") || event.getName().getPath().contains("entity")){
// Get the filename of the loot table json, for well-behaved mods this will be the entity name
String[] split = event.getName().getPath().split("/");
String entityName = split[split.length - 1];
EntityEntry entry = ForgeRegistries.ENTITIES.getValue(new ResourceLocation(entityName));
if(entry == null) return; // If this is true it didn't work :(
Class entityClass = entry.getEntityClass();
if(EnumCreatureType.MONSTER.getCreatureClass().isAssignableFrom(entityClass)){
if (Wizardry.settings.injectMobDrops) {
// Let's hope mods will play nice and store their entity loot tables under 'entities' or 'entity'
// If not, packmakers will have to sort it out themselves using the whitelist/blacklist
if (Arrays.asList(Wizardry.settings.mobLootTableWhitelist).contains(event.getName())) {
event.getTable().addPool(getAdditive(Wizardry.MODID + ":entities/mob_additions", Wizardry.MODID + "_additional_mob_drops"));
} else if (!Arrays.asList(Wizardry.settings.mobLootTableBlacklist).contains(event.getName())
&& event.getName().getPath().contains("entities") || event.getName().getPath().contains("entity")) {
// Get the filename of the loot table json, for well-behaved mods this will be the entity name
String[] split = event.getName().getPath().split("/");
String entityName = split[split.length - 1];
EntityEntry entry = ForgeRegistries.ENTITIES.getValue(new ResourceLocation(entityName));
if (entry == null) {
return; // If this is true it didn't work :(
}
Class entityClass = entry.getEntityClass();
if (EnumCreatureType.MONSTER.getCreatureClass().isAssignableFrom(entityClass)) {
event.getTable().addPool(getAdditive(Wizardry.MODID + ":entities/mob_additions", Wizardry.MODID + "_additional_mob_drops"));
}
}
}
// Fishing loot
@@ -57,6 +57,9 @@ public final class WizardryPotions {
public static final Potion frost_step = placeholder();
public static final Potion mark_of_sacrifice = placeholder();
public static final Potion mirage = placeholder();
public static final Potion oakflesh = placeholder();
public static final Potion ironflesh = placeholder();
public static final Potion diamondflesh = placeholder();
/**
* Sets both the registry and unlocalised names of the given potion, then registers it with the given registry. Use
@@ -201,6 +204,10 @@ public final class WizardryPotions {
public void spawnCustomParticle(World world, double x, double y, double z){} // We only want the syncing
}.setBeneficial());
registerPotion(registry, "oakflesh", new PotionOakflesh(false, 0).setBeneficial());
registerPotion(registry, "ironflesh", new PotionIronflesh(false, 0).setBeneficial());
registerPotion(registry, "diamondflesh", new PotionDiamondflesh(false, 0).setBeneficial());
}
}
@@ -33,7 +33,7 @@ public class ConjureBlock extends SpellRay {
@Override
protected boolean onBlockHit(World world, BlockPos pos, EnumFacing side, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){
if(caster.isSneaking() && world.getBlockState(pos).getBlock() == WizardryBlocks.spectral_block){
if(caster != null && caster.isSneaking() && world.getBlockState(pos).getBlock() == WizardryBlocks.spectral_block){
if(!world.isRemote){
// Dispelling of blocks
@@ -53,7 +53,7 @@ public class CurseOfSoulbinding extends SpellRay {
@Override
protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){
if(EntityUtils.isLiving(target) && caster instanceof EntityPlayer){
WizardData data = WizardData.get((EntityPlayer)caster);
if(data != null){
@@ -66,7 +66,7 @@ public class CurseOfSoulbinding extends SpellRay {
}
}
}
return true;
}
@@ -79,7 +79,7 @@ public class CurseOfSoulbinding extends SpellRay {
protected boolean onMiss(World world, EntityLivingBase caster, Vec3d origin, Vec3d direction, int ticksInUse, SpellModifiers modifiers){
return true;
}
@Override
protected void spawnParticle(World world, double x, double y, double z, double vx, double vy, double vz){
ParticleBuilder.create(Type.DARK_MAGIC).pos(x, y, z).clr(0.4f, 0, 0).spawn(world);
@@ -103,9 +103,9 @@ public class CurseOfSoulbinding extends SpellRay {
Entity entity = EntityUtils.getEntityByUUID(player.world, iterator.next());
if(entity == null) iterator.remove();
if(entity instanceof EntityLivingBase){
if (entity == null || (entity instanceof EntityLivingBase && !((EntityLivingBase) entity).isPotionActive(WizardryPotions.curse_of_soulbinding))) {
iterator.remove();
} else if (entity instanceof EntityLivingBase) {
// Retaliatory effect
if(DamageSafetyChecker.attackEntitySafely(entity, MagicDamage.causeDirectMagicDamage(player,
MagicDamage.DamageType.MAGIC, true), event.getAmount(), event.getSource().getDamageType(),
@@ -5,6 +5,7 @@ import electroblob.wizardry.constants.Constants;
import electroblob.wizardry.entity.living.ISpellCaster;
import electroblob.wizardry.event.SpellCastEvent;
import electroblob.wizardry.item.SpellActions;
import electroblob.wizardry.registry.Spells;
import electroblob.wizardry.registry.WizardryItems;
import electroblob.wizardry.registry.WizardryPotions;
import electroblob.wizardry.util.ParticleBuilder;
@@ -24,11 +25,14 @@ import javax.annotation.Nullable;
@Mod.EventBusSubscriber
public class EmpoweringPresence extends SpellAreaEffect {
/** The fraction by which potency is increased per level of the empowerment effect. */
public static final String POTENCY_PER_LEVEL = "potency_per_level";
public EmpoweringPresence(){
super("empowering_presence", SpellActions.POINT_UP, false);
this.alwaysSucceed(true);
this.targetAllies(true);
addProperties(EFFECT_DURATION, EFFECT_STRENGTH);
addProperties(EFFECT_DURATION, EFFECT_STRENGTH, POTENCY_PER_LEVEL);
}
@Override
@@ -62,7 +66,7 @@ public class EmpoweringPresence extends SpellAreaEffect {
if(event.getCaster() != null && event.getCaster().isPotionActive(WizardryPotions.empowerment)
&& !(event.getSpell() instanceof EmpoweringPresence)){ // Prevent exponential empowerment stacking!
float potency = 1 + Constants.EMPOWERMENT_POTENCY_PER_LEVEL
float potency = 1 + Spells.empowering_presence.getProperty(POTENCY_PER_LEVEL).floatValue()
* (event.getCaster().getActivePotionEffect(WizardryPotions.empowerment).getAmplifier() + 1);
event.getModifiers().set(SpellModifiers.POTENCY,
@@ -59,18 +59,19 @@ public class FrostRay extends SpellRay {
this.getNameForTranslationFormatted()), true);
// This now only damages in line with the maxHurtResistantTime. Some mods don't play nicely and fiddle
// with this mechanic for their own purposes, so this line makes sure that doesn't affect wizardry.
}else if(ticksInUse % ((EntityLivingBase)target).maxHurtResistantTime == 1){
}else{
// For frost ray the entity can move slightly, unlike freeze
((EntityLivingBase)target).addPotionEffect(new PotionEffect(WizardryPotions.frost,
(int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)),
getProperty(EFFECT_STRENGTH).intValue()));
float damage = getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY);
if(target instanceof EntityBlaze || target instanceof EntityMagmaCube) damage *= 2;
EntityUtils.attackEntityWithoutKnockback(target, MagicDamage.causeDirectMagicDamage(caster,
DamageType.FROST), damage);
if(ticksInUse % ((EntityLivingBase)target).maxHurtResistantTime == 1){
float damage = getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY);
if(target instanceof EntityBlaze || target instanceof EntityMagmaCube) damage *= 2;
EntityUtils.attackEntityWithoutKnockback(target, MagicDamage.causeDirectMagicDamage(caster,
DamageType.FROST), damage);
}
}
}
@@ -8,6 +8,7 @@ import electroblob.wizardry.util.ParticleBuilder.Type;
import electroblob.wizardry.util.SpellModifiers;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.SoundEvents;
import net.minecraft.util.EnumHand;
import net.minecraft.world.World;
@@ -24,14 +25,14 @@ public class Glide extends Spell {
@Override
protected void playSound(World world, EntityLivingBase entity, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){
if(ticksInUse == 0 && world.isRemote) Wizardry.proxy.playSpellSoundLoop(entity, this, this.sounds[0], this.sounds[0], this.sounds[0],
if(ticksInUse == 0 && world.isRemote) Wizardry.proxy.playSpellSoundLoop(entity, this, this.sounds[0], this.sounds[0], SoundEvents.UI_TOAST_OUT,
WizardrySounds.SPELLS, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f));
}
@Override
protected void playSound(World world, double x, double y, double z, int ticksInUse, int duration, SpellModifiers modifiers, String... sounds){
if(ticksInUse == 0 && world.isRemote){
Wizardry.proxy.playSpellSoundLoop(world, x, y, z, this, this.sounds[0], this.sounds[0], this.sounds[0],
Wizardry.proxy.playSpellSoundLoop(world, x, y, z, this, this.sounds[0], this.sounds[0], SoundEvents.UI_TOAST_OUT,
WizardrySounds.SPELLS, volume, pitch + pitchVariation * (world.rand.nextFloat() - 0.5f), duration);
}
}
@@ -63,7 +63,7 @@ public class MarkSacrifice extends SpellRay {
PotionEffect effect = event.getEntityLiving().getActivePotionEffect(WizardryPotions.mark_of_sacrifice);
if(effect != null && event.getSource().isMagicDamage()){
event.setAmount(event.getAmount() * (1 + effect.getAmplifier() * DAMAGE_INCREASE_PER_LEVEL));
event.setAmount(event.getAmount() * (1 + (1 + effect.getAmplifier()) * DAMAGE_INCREASE_PER_LEVEL));
event.getEntityLiving().removePotionEffect(WizardryPotions.mark_of_sacrifice);
}
}
@@ -111,6 +111,9 @@ public class MindControl extends SpellRay {
/** 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(Entity target){
// TODO: Add a max health limit that scales with potency
return target instanceof EntityLiving && target.isNonBoss() && !(target instanceof INpc)
&& !(target instanceof EntityEvilWizard) && !Arrays.asList(Wizardry.settings.mindControlTargetsBlacklist)
.contains(EntityList.getKey(target.getClass()));
@@ -30,9 +30,14 @@ public class Paralysis extends SpellRay {
* will end. */
private static final String CRITICAL_HEALTH = "critical_health";
/**
* Multiplier for affecting players
*/
private static final String PLAYER_EFFECT_DURATION_MULTIPLIER = "player_effect_duration_multiplier";
public Paralysis(){
super("paralysis", SpellActions.POINT, false);
addProperties(DAMAGE, EFFECT_DURATION, CRITICAL_HEALTH);
addProperties(DAMAGE, EFFECT_DURATION, CRITICAL_HEALTH, PLAYER_EFFECT_DURATION_MULTIPLIER);
}
@Override
@@ -57,9 +62,10 @@ public class Paralysis extends SpellRay {
target.attackEntityFrom(MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK),
getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY));
}
float durationMultiplier = target instanceof EntityPlayer ? modifiers.get(PLAYER_EFFECT_DURATION_MULTIPLIER) : 1.0f;
((EntityLivingBase)target).addPotionEffect(new PotionEffect(WizardryPotions.paralysis,
(int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)), 0));
(int)(getProperty(EFFECT_DURATION).floatValue() * durationMultiplier * modifiers.get(WizardryItems.duration_upgrade)), 0));
}
return false;
@@ -1,6 +1,8 @@
package electroblob.wizardry.spell;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.data.WizardData;
import electroblob.wizardry.event.ResurrectionEvent;
import electroblob.wizardry.item.ISpellCastingItem;
import electroblob.wizardry.item.SpellActions;
import electroblob.wizardry.packet.PacketResurrection;
@@ -8,6 +10,7 @@ import electroblob.wizardry.packet.WizardryPacketHandler;
import electroblob.wizardry.registry.Spells;
import electroblob.wizardry.registry.WizardryItems;
import electroblob.wizardry.util.ParticleBuilder;
import electroblob.wizardry.util.ParticleBuilder.Type;
import electroblob.wizardry.util.SpellModifiers;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
@@ -16,11 +19,16 @@ import net.minecraft.util.EnumHand;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import java.util.Arrays;
import java.util.Comparator;
@EventBusSubscriber
public class Resurrection extends Spell {
public static final String WAIT_TIME = "wait_time";
@@ -55,6 +63,9 @@ public class Resurrection extends Spell {
.orElse(null);
if(nearestDeadAlly != null){
if(MinecraftForge.EVENT_BUS.post(new ResurrectionEvent(nearestDeadAlly, caster))) return false;
// When the player entity dies, it is removed from world#loadedEntityList. However, it is NOT removed
// from playerEntityList (and probably a few other places) until respawn is clicked, and since that
// never happens here we need to clean up those references or the player will have duplicate entries
@@ -112,4 +123,42 @@ public class Resurrection extends Spell {
&& ((ISpellCastingItem)stack.getItem()).canCast(stack, Spells.resurrection, player, EnumHand.MAIN_HAND, 0, new SpellModifiers());
}
}
@SubscribeEvent
public static void onPlayerTickEvent(LivingUpdateEvent event){
if(event.getEntity() instanceof EntityPlayer){
EntityPlayer player = (EntityPlayer)event.getEntity();
if(player.world.isRemote && !player.isEntityAlive()){
EntityPlayer firstPersonPlayer = Wizardry.proxy.getThePlayer();
if(WizardData.get(firstPersonPlayer).isPlayerAlly(player)){
ItemStack wand = firstPersonPlayer.getHeldItemMainhand();
if(!(wand.getItem() instanceof ISpellCastingItem)){
wand = firstPersonPlayer.getHeldItemOffhand();
if(!(wand.getItem() instanceof ISpellCastingItem)) return;
}
if(((ISpellCastingItem)wand.getItem()).getCurrentSpell(wand) == Spells.resurrection){
// TODO: Find some way of getting at the modifiers before the spell is cast
int waitTime = Spells.resurrection.getProperty(WAIT_TIME).intValue();
if(player.deathTime > waitTime){
ParticleBuilder.create(Type.SPARKLE, player.world.rand, player.posX, player.posY + 0.5, player.posZ, 0.5, false)
.clr(1, 1, 0.3f).vel(0, 0.02, 0).spawn(player.world);
}else{
ParticleBuilder.create(Type.DUST, player.world.rand, player.posX, player.posY + 0.5, player.posZ, 0.5, false)
.clr(1, 1, 0.3f).vel(0, 0.02, 0).time(50).spawn(player.world);
}
}
}
}
}
}
}
@@ -189,7 +189,7 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
private static int nextSpellId = 0;
/** The spell's integer ID, mainly used for networking. */
// This was added after I learnt the hard way why you can't assume Forge's registry IDs are sequential...
private final int id;
private int id;
/**
* This constructor should be called from any subclasses, either feeding in the constants directly or through their
@@ -225,6 +225,7 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
this.icon = new ResourceLocation(modID, "textures/spells/" + name + ".png");
this.sounds = createSounds();
this.id = nextSpellId++;
Wizardry.logger.debug("Registering spell " + this.unlocalisedName +" with networkID " + id);
this.items(WizardryItems.spell_book, WizardryItems.scroll);
this.npcSelector((e, o) -> false);
}
@@ -560,6 +561,11 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
return id;
}
/** Sets the networkID of this spell. Do not call this or it will cause all packets to fail. */
public void setId(int id) {
this.id = id;
}
/** Returns the {@code ResourceLocation} for this spell's icon. */
public final ResourceLocation getIcon(){
return icon;
@@ -125,7 +125,8 @@ public class SpellBuff extends Spell {
@Override
public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){
// Wizards can only cast a buff spell if they don't already have its effects.
if(caster.getActivePotionMap().keySet().containsAll(potionSet)) return false;
// Some buff spells doesn't add any potion effects, those are ignored by this check
if(!potionSet.isEmpty() && caster.getActivePotionMap().keySet().containsAll(potionSet)) return false;
// Only return on the server side or the client probably won't spawn particles
if(!this.applyEffects(caster, modifiers) && !world.isRemote) return false;
if(world.isRemote) this.spawnParticles(world, caster, modifiers);
@@ -1,51 +0,0 @@
package electroblob.wizardry.spell;
import electroblob.wizardry.item.SpellActions;
import electroblob.wizardry.util.BlockUtils;
import electroblob.wizardry.util.ParticleBuilder;
import electroblob.wizardry.util.ParticleBuilder.Type;
import electroblob.wizardry.util.SpellModifiers;
import net.minecraft.entity.monster.EntityIronGolem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public class SummonIronGolem extends Spell {
public SummonIronGolem(){
super("summon_iron_golem", SpellActions.SUMMON, false);
addProperties(SpellMinion.SUMMON_RADIUS);
soundValues(1, 1.1f, 0.2f);
}
@Override
public boolean cast(World world, EntityPlayer caster, EnumHand hand, int ticksInUse, SpellModifiers modifiers){
BlockPos pos = BlockUtils.findNearbyFloorSpace(caster, getProperty(SpellMinion.SUMMON_RADIUS).intValue(),
getProperty(SpellMinion.SUMMON_RADIUS).intValue());
if(pos == null) return false;
if(!world.isRemote){
EntityIronGolem golem = new EntityIronGolem(world);
golem.setPosition(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5);
golem.setPlayerCreated(true);
world.spawnEntity(golem);
}else{
for(int i=0; i<10; i++){
double x = pos.getX() + world.rand.nextDouble() * 2 - 1;
double y = pos.getY() + 0.5 + world.rand.nextDouble();
double z = pos.getZ() + world.rand.nextDouble() * 2 - 1;
ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).clr(0.6f, 0.6f, 1).spawn(world);
}
}
this.playSound(world, caster, ticksInUse, -1, modifiers);
return true;
}
}
@@ -2,6 +2,7 @@ package electroblob.wizardry.tileentity;
import electroblob.wizardry.block.BlockReceptacle;
import electroblob.wizardry.constants.Element;
import electroblob.wizardry.event.ImbuementActivateEvent;
import electroblob.wizardry.item.IManaStoringItem;
import electroblob.wizardry.item.ItemWizardArmour;
import electroblob.wizardry.registry.*;
@@ -24,6 +25,7 @@ import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraft.world.storage.loot.LootContext;
import net.minecraft.world.storage.loot.LootTable;
import net.minecraftforge.common.MinecraftForge;
import org.apache.commons.lang3.ArrayUtils;
import javax.annotation.Nullable;
@@ -233,6 +235,14 @@ public class TileEntityImbuementAltar extends TileEntity implements ITickable {
*/
public static ItemStack getImbuementResult(ItemStack input, Element[] receptacleElements, boolean fullLootGen, World world, EntityPlayer lastUser){
ItemStack eventResult = ItemStack.EMPTY;
if (world != null && MinecraftForge.EVENT_BUS.post(new ImbuementActivateEvent(input, receptacleElements, world, lastUser, eventResult))) {
// return the stack if something changes the result from an empty stack.
//noinspection ConstantConditions
if (eventResult != ItemStack.EMPTY) return eventResult;
}
if(input.getItem() instanceof ItemWizardArmour && ((ItemWizardArmour)input.getItem()).element == null){
if(Arrays.stream(receptacleElements).distinct().count() == 1 && receptacleElements[0] != null){ // All the same element
@@ -34,7 +34,9 @@ import java.util.Random;
* <code>ParticleBuilder.create(Type.SPARKLE).pos(x, y, z).vel(vx, vy, vz).clr(r, g, b).spawn(world);</code>
* <p></p>
* It also goes without saying that <b>this class should only ever be used client-side</b>. Attempting to spawn particles
* on the server side will not work and will print a warning to the console.
* on the server side will not work and will print a warning to the console. {@code ParticleBuilder} is not threadsafe
* and attempting to call it from multiple threads at once will very likely cause an {@link IllegalStateException}.
*
* @author Electroblob
* @since Wizardry 4.2
*/
@@ -0,0 +1,32 @@
package electroblob.wizardry.util;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.spell.Spell;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
/**
* Helper class which ensures that all spellpack spell networkIDs are distributed in alphabetical order. Introducing this was necessary as mods (especially with
* (load-after) dependencies were not always registering their spells in the exact same order. This is definitely
*/
public class SpellNetworkIDSorter {
public static void init() {
//reorder network IDs based on addon modids. This is necessary as modloading order doesn't seem to be guaranteed to match between various servers and clients
Wizardry.logger.debug("Reordering all spell NetworkIDs based on addon modid alphabetical order");
// the first available ID after all default spells
int nextSpellId = (int) Spell.getAllSpells().stream().filter(spell -> spell.getRegistryName().getNamespace().equals(Wizardry.MODID)).count() + 1;
List<Spell> addonSpells = Spell.getAllSpells().stream().filter(spell -> !spell.getRegistryName().getNamespace().equals(Wizardry.MODID)).collect(Collectors.toList());
// sorting spells
addonSpells.sort(Comparator.comparing((Spell o) -> o.getRegistryName().toString()));
for (Spell spell : addonSpells) {
Wizardry.logger.debug("Updating networkID of spell " + spell.getRegistryName().toString() + " from " + spell.networkID() + " to " + nextSpellId);
spell.setId(nextSpellId++);
}
}
}
@@ -83,6 +83,7 @@ item.ebwizardry\:arcane_tome.desc=Upgrades any %1$s wand with sufficient progres
item.ebwizardry\:wizard_handbook.name=The Wizard's Handbook
item.ebwizardry\:wizard_handbook.author=by %1$s
item.ebwizardry\:wizard_handbook.desc=Your not-so-pocket-sized guide to the arcane arts! A must-have for any aspiring wizard who seeks to learn the secrets of magic.\n\nRight-click while holding this book to read it.
item.ebwizardry\:wizard_handbook.disabled=This item was disabled in the config!
item.ebwizardry\:wand.generic=wand
@@ -402,6 +403,10 @@ item.ebwizardry\:generic.disabled=This item has been disabled in the config
item.ebwizardry\:ring.generic.desc=Equip this ring in the Baubles inventory or by placing it on your hotbar. Up to 2 rings may be equipped at once.
item.ebwizardry\:amulet.generic.desc=Equip this amulet in the Baubles inventory or by placing it on your hotbar. Only one amulet may be equipped at a time.
item.ebwizardry\:charm.generic.desc=Equip this charm in the Baubles inventory or by placing it on your hotbar. Only one charm may be equipped at a time.
item.ebwizardry\:belt.generic.desc=Equip this belt in the Baubles inventory or by placing it on your hotbar. Only one belt may be equipped at a time.
item.ebwizardry\:body.generic.desc=Equip this body item in the Baubles inventory or by placing it on your hotbar. Only one body item may be equipped at a time.
item.ebwizardry\:trinket.generic.desc=Equip this trinket in the Baubles inventory or by placing it on your hotbar. Only one trinklet may be equipped at a time.
item.ebwizardry\:head.generic.desc=Equip this headgear in the Baubles inventory or by placing it on your hotbar. Only one headgear may be equipped at a time.
item.ebwizardry\:ring_condensing.name=Ring of Condensing
item.ebwizardry\:ring_condensing.desc=Slowly regenerates mana for all wands on your hotbar
@@ -438,7 +443,7 @@ item.ebwizardry\:ring_hammer.desc=Lightning hammers can be picked up and thrown
item.ebwizardry\:ring_stormcloud.name=Lokenzen's Ring
item.ebwizardry\:ring_stormcloud.desc=Stormcloud moves towards targets and lasts longer with every strike
item.ebwizardry\:ring_soulbinding.name=Soulwalker's Ring
item.ebwizardry\:ring_soulbinding.desc=Creatures damaged by necromancy spells become soulbound to you
item.ebwizardry\:ring_soulbinding.desc=Creatures damaged by necromancy spells become soulbound to you for 20 seconds
item.ebwizardry\:ring_leeching.name=Ring of Leeching
item.ebwizardry\:ring_leeching.desc=All necromancy attacks have a 30%% chance to trigger a life drain effect
item.ebwizardry\:ring_necromancy_melee.name=Ring of Necrotic Touch
@@ -732,6 +737,7 @@ entity.ebwizardry\:evil_wizard.name=Wizard
entity.ebwizardry\:decoy.name=Decoy
entity.ebwizardry\:vex_minion.name=Vex
entity.ebwizardry\:remnant.name=Remnant
entity.ebwizardry\:spectral_golem.name=Spectral Golem
entity.ebwizardry\:magic_missile.name=Magic
entity.ebwizardry\:arc.name=Magic
@@ -758,6 +764,7 @@ entity.ebwizardry\:smoke_bomb.name=Magic
entity.ebwizardry\:ice_spike.name=Magic
entity.ebwizardry\:combustion_rune.name=Magic
entity.ebwizardry\:flamecatcher_arrow.name=Magic
entity.ebwizardry\:conjured_arrow.name=Magic
entity.ebwizardry\:black_hole.name=Black Hole
entity.ebwizardry\:shield.name=Shield
@@ -1075,7 +1082,7 @@ spell.ebwizardry\:stormcloud=Stormcloud
spell.ebwizardry\:summon_blaze=Summon Blaze
spell.ebwizardry\:summon_ice_giant=Summon Ice Giant
spell.ebwizardry\:summon_ice_wraith=Summon Ice Wraith
spell.ebwizardry\:summon_iron_golem=Summon Iron Golem
spell.ebwizardry\:summon_iron_golem=Summon Spectral Golem
spell.ebwizardry\:summon_lightning_wraith=Summon Lightning Wraith
spell.ebwizardry\:summon_phoenix=Summon Phoenix
spell.ebwizardry\:summon_shadow_wraith=Summon Shadow Wraith
@@ -1203,7 +1210,7 @@ spell.ebwizardry\:intimidate.desc=Emits an intimidating growl which causes nearb
spell.ebwizardry\:invigorating_presence.desc=Grants the caster and all nearby allies increased strength for 45 seconds.
spell.ebwizardry\:invisibility.desc=Makes the caster invisible for 30 seconds.
spell.ebwizardry\:invoke_weather.desc=Changes the weather in the world.
spell.ebwizardry\:ironflesh.desc=Greatly improves the caster's damage resistance for 30 seconds.
spell.ebwizardry\:ironflesh.desc=Greatly improves the caster's armor and knockback resistance for 30 seconds.
spell.ebwizardry\:leap.desc=Causes the caster to jump upwards several blocks and slightly forward.
spell.ebwizardry\:levitation.desc=Raises the caster upwards while the use item button is held. Will also negate fall damage if used before hitting the ground.
spell.ebwizardry\:life_drain.desc=Creates a stream of withering energy in the direction you are pointing which drains the life of the target and uses it to gradually regenerate your health.
@@ -1226,7 +1233,7 @@ spell.ebwizardry\:mine.desc=Breaks the block the caster is looking at. Potency w
spell.ebwizardry\:mirage.desc=Creates an illusion where the caster appears to be a few blocks away from their actual position, blinking around every few seconds. The illusion lasts for 20 seconds.
spell.ebwizardry\:muffle.desc=Silences any sounds made by the caster for 30 seconds. When muffled, mobs can only detect you when looking towards you.
spell.ebwizardry\:none.desc=To get a spell book with the /give command, use id\: /give [player] ebwizardry\:spell_book 1 [spell id] (if you found this book in a chest, some other mod has messed things up).
spell.ebwizardry\:oakflesh.desc=Improves the caster's damage resistance for 30 seconds.
spell.ebwizardry\:oakflesh.desc=Slightly improves the caster's vitality and damage resistance for 30 seconds.
spell.ebwizardry\:paralysis.desc=Delivers a powerful lightning bolt that paralyses targets for 5 seconds. Paralysed creatures cannot move and will still take damage - but too much will snap the creature out of paralysis.
spell.ebwizardry\:permafrost.desc=Spreads a layer of slippery ice on the ground where you are pointing, the extreme cold of which causes creatures to slowly take damage.
spell.ebwizardry\:petrify.desc=Turns the target to stone until broken out, with a chance for it to break out when it is dark. The target cannot move or do anything while petrified but is also impervious to all damage.
@@ -1400,6 +1407,9 @@ potion.ebwizardry\:containment=Containment
potion.ebwizardry\:frost_step=Frost Step
potion.ebwizardry\:mark_of_sacrifice=Mark of Sacrifice
potion.ebwizardry\:mirage=Mirage
potion.ebwizardry\:oakflesh=Oakflesh
potion.ebwizardry\:ironflesh=Ironflesh
potion.ebwizardry\:diamondflesh=Diamondflesh
enchantment.ebwizardry\:magic_sword=Imbuement
enchantment.ebwizardry\:magic_bow=Imbuement
@@ -1524,6 +1534,20 @@ config.ebwizardry.slow_time_affects_players=Slow Time Affects Players
config.ebwizardry.slow_time_affects_players.tooltip=Whether players are slowed when another nearby player uses the slow time spell. If this is disabled, mobs and projectiles will still be affected but players will move at normal speed.
config.ebwizardry.bonemeal_grows_crystal_flowers=Bonemeal Grows Crystal Flowers
config.ebwizardry.bonemeal_grows_crystal_flowers.tooltip=Whether using bonemeal on grass blocks has a chance to grow crystal flowers.
config.ebwizardry.wands_must_be_held_to_decrement_cooldown=Wands Must Be Held To Decrement Cooldown
config.ebwizardry.wands_must_be_held_to_decrement_cooldown.tooltip=Whether wands only decrement their cooldowns if a player holds them.
config.ebwizardry.cooldown_reduction_per_level=Cooldown Reduction Per Level
config.ebwizardry.cooldown_reduction_per_level.tooltip=The fraction by which cooldowns are reduced for each level of cooldown upgrade.
config.ebwizardry.potency_increase_per_tier=Potency Increase Per Tier
config.ebwizardry.potency_increase_per_tier.tooltip=The fraction by which potency is increased for each tier of matching wand. May cause extreme lag with high values!
config.ebwizardry.duration_increase_per_level=Duration Increase Per Level
config.ebwizardry.duration_increase_per_level.tooltip=The fraction by which spell duration is increased for each level of duration upgrade.
config.ebwizardry.range_increase_per_level=Range Increase Per Level
config.ebwizardry.range_increase_per_level.tooltip=The fraction by which spell range is increased for each level of range upgrade. May cause extreme lag with high values!
config.ebwizardry.blast_increase_per_level=Blast Increase Per Level
config.ebwizardry.blast_increase_per_level.tooltip=The fraction by which spell blast is increased for each level of blast upgrade. May cause extreme lag with high values!
config.ebwizardry.frost_slowness_increase_per_level=Frost Slowness Increase Per Level
config.ebwizardry.frost_slowness_increase_per_level.tooltip=The fraction by which movement speed is reduced per level of frost effect.
config.ebwizardry.category.difficulty=Difficulty Settings
config.ebwizardry.category.difficulty.tooltip=Configure wizardry's difficulty
@@ -1580,6 +1604,8 @@ config.ebwizardry.mob_loot_table_whitelist=Mob Loot Table Whitelist
config.ebwizardry.mob_loot_table_whitelist.tooltip=Whitelist for loot tables to inject additional mob drops (as specified in loot_tables/entities/mob_additions.json) into. Wizardry makes a best guess as to which loot tables belong to hostile mobs, but this may not always be correct or appropriate; add loot table locations (not entity IDs) to this list to manually include them.
config.ebwizardry.mob_loot_table_blacklist=Mob Loot Table Blacklist
config.ebwizardry.mob_loot_table_blacklist.tooltip=Blacklist for loot tables to inject additional mob drops (as specified in loot_tables/entities/mob_additions.json) into. Wizardry makes a best guess as to which loot tables belong to hostile mobs, but this may not always be correct or appropriate; add loot table locations (not entity IDs) to this list to manually exclude them.
config.ebwizardry.inject_mob_drops=Allow Wizardry Mob Loot
config.ebwizardry.inject_mob_drops.tooltip=Whether to inject Wizardry loot to mobs, based on the loot table 'Mob Loot Table Whitelist' / 'Mob Loot Table Blacklist' settings. If disabled, the lists won't have any effect!
config.ebwizardry.mob_spawn_dimensions=Mob Spawning Dimensions
config.ebwizardry.mob_spawn_dimensions.tooltip=List of ids of dimensions in which wizardry's hostile mobs can spawn.
config.ebwizardry.mob_spawn_biome_blacklist=Mob Spawning Biome Blacklist
File diff suppressed because it is too large Load Diff
@@ -200,16 +200,16 @@ item.ebwizardry\:identification_scroll.desc=알 수 없는 주문서나 두루
item.ebwizardry\:identification_scroll.desc_extended=오른쪽 버튼을 클릭하여 식별하지 않은 주문서를 식별할 수 있습니다.
item.ebwizardry\:identification_scroll.nothing_to_identify=식별할 주문이 없습니다!
item.ebwizardry\:resplendent_thread.name=찬란
item.ebwizardry\:resplendent_thread.name=찬란타래
item.ebwizardry\:resplendent_thread.desc=일반적인 마법사의 갑옷을 학자의 갑옷으로 강화합니다
item.ebwizardry\:resplendent_thread.desc_extended=희미하게 빛나는 실로 신비로운 무늬를 수놓아 로브의 질을 높이고, 마법 부여의 효과를 상승시킵니다.\n\n신비로운 작업대에서 마법사 갑옷에 이 강화를 적용할 수 있습니다.
item.ebwizardry\:crystal_silver_plating.name=은도금된 수정
item.ebwizardry\:crystal_silver_plating.desc=일반적인 마법사의 갑옷을 전투법사의 갑옷으로 강화합니다
item.ebwizardry\:crystal_silver_plating.desc_extended=엘다르의 공장에서 만들어진 거의 신화적인 합금으로, 우수한 마법 굴절도를 가지고 있습니다.\n\n신비로운 작업대에서 마법사 갑옷에 이 강화를 적용할 수 있습니다.
item.ebwizardry\:crystal_silver_plating.desc_extended=엘다르의 대장간에서 만들어진 거의 신화적인 합금으로, 우수한 마법 굴절도를 가지고 있습니다.\n\n신비로운 작업대에서 마법사 갑옷에 이 강화를 적용할 수 있습니다.
item.ebwizardry\:ethereal_crystalweave.name=천상의 수정천
item.ebwizardry\:ethereal_crystalweave.desc=일반적인 마법사의 갑옷을 워록의 갑옷으로 강화합니다
item.ebwizardry\:ethereal_crystalweave.desc=일반적인 마법사의 갑옷을 주술사의 갑옷으로 강화합니다
item.ebwizardry\:ethereal_crystalweave.desc_extended=동물의 가죽처럼 두껍지만 한 장의 종이보다 가벼운 마나의 천입니다.\n\n신비로운 작업대에서 마법사 갑옷에 이 강화를 적용할 수 있습니다.
item.ebwizardry\:magic_silk.name=마법 비단
@@ -346,45 +346,45 @@ item.ebwizardry\:battlemage_chestplate_healing.name=치유 전투법사 흉갑
item.ebwizardry\:battlemage_leggings_healing.name=치유 전투법사 각반
item.ebwizardry\:battlemage_boots_healing.name=치유 전투법사 부츠
item.ebwizardry\:warlock_hood.name=워록 후드
item.ebwizardry\:warlock_robe.name=워록 로브
item.ebwizardry\:warlock_leggings.name=워록 각반
item.ebwizardry\:warlock_boots.name=워록 부츠
item.ebwizardry\:warlock_hood.name=주술사 후드
item.ebwizardry\:warlock_robe.name=주술사 로브
item.ebwizardry\:warlock_leggings.name=주술사 각반
item.ebwizardry\:warlock_boots.name=주술사 부츠
item.ebwizardry\:warlock_hood_fire.name=화염워록 후드
item.ebwizardry\:warlock_robe_fire.name=화염워록 로브
item.ebwizardry\:warlock_leggings_fire.name=화염워록 각반
item.ebwizardry\:warlock_boots_fire.name=화염워록 부츠
item.ebwizardry\:warlock_hood_fire.name=화염주술사 후드
item.ebwizardry\:warlock_robe_fire.name=화염주술사 로브
item.ebwizardry\:warlock_leggings_fire.name=화염주술사 각반
item.ebwizardry\:warlock_boots_fire.name=화염주술사 부츠
item.ebwizardry\:warlock_hood_ice.name=얼음워록 후드
item.ebwizardry\:warlock_robe_ice.name=얼음워록 로브
item.ebwizardry\:warlock_leggings_ice.name=얼음워록 각반
item.ebwizardry\:warlock_boots_ice.name=얼음워록 부츠
item.ebwizardry\:warlock_hood_ice.name=얼음주술사 후드
item.ebwizardry\:warlock_robe_ice.name=얼음주술사 로브
item.ebwizardry\:warlock_leggings_ice.name=얼음주술사 각반
item.ebwizardry\:warlock_boots_ice.name=얼음주술사 부츠
item.ebwizardry\:warlock_hood_lightning.name=벼락워록 후드
item.ebwizardry\:warlock_robe_lightning.name=벼락워록 로브
item.ebwizardry\:warlock_leggings_lightning.name=벼락워록 각반
item.ebwizardry\:warlock_boots_lightning.name=벼락워록 부츠
item.ebwizardry\:warlock_hood_lightning.name=벼락주술사 후드
item.ebwizardry\:warlock_robe_lightning.name=벼락주술사 로브
item.ebwizardry\:warlock_leggings_lightning.name=벼락주술사 각반
item.ebwizardry\:warlock_boots_lightning.name=벼락주술사 부츠
item.ebwizardry\:warlock_hood_necromancy.name=사령워록 후드
item.ebwizardry\:warlock_robe_necromancy.name=사령워록 로브
item.ebwizardry\:warlock_leggings_necromancy.name=사령워록 각반
item.ebwizardry\:warlock_boots_necromancy.name=사령워록 부츠
item.ebwizardry\:warlock_hood_necromancy.name=사령주술사 후드
item.ebwizardry\:warlock_robe_necromancy.name=사령주술사 로브
item.ebwizardry\:warlock_leggings_necromancy.name=사령주술사 각반
item.ebwizardry\:warlock_boots_necromancy.name=사령주술사 부츠
item.ebwizardry\:warlock_hood_earth.name=대지워록 후드
item.ebwizardry\:warlock_robe_earth.name=대지워록 로브
item.ebwizardry\:warlock_leggings_earth.name=대지워록 각반
item.ebwizardry\:warlock_boots_earth.name=대지워록 부츠
item.ebwizardry\:warlock_hood_earth.name=대지주술사 후드
item.ebwizardry\:warlock_robe_earth.name=대지주술사 로브
item.ebwizardry\:warlock_leggings_earth.name=대지주술사 각반
item.ebwizardry\:warlock_boots_earth.name=대지주술사 부츠
item.ebwizardry\:warlock_hood_sorcery.name=신비워록 후드
item.ebwizardry\:warlock_robe_sorcery.name=신비워록 로브
item.ebwizardry\:warlock_leggings_sorcery.name=신비워록 각반
item.ebwizardry\:warlock_boots_sorcery.name=신비워록 부츠
item.ebwizardry\:warlock_hood_sorcery.name=신비주술사 후드
item.ebwizardry\:warlock_robe_sorcery.name=신비주술사 로브
item.ebwizardry\:warlock_leggings_sorcery.name=신비주술사 각반
item.ebwizardry\:warlock_boots_sorcery.name=신비주술사 부츠
item.ebwizardry\:warlock_hood_healing.name=치유워록 후드
item.ebwizardry\:warlock_robe_healing.name=치유워록 로브
item.ebwizardry\:warlock_leggings_healing.name=치유워록 각반
item.ebwizardry\:warlock_boots_healing.name=치유워록 부츠
item.ebwizardry\:warlock_hood_healing.name=치유주술사 후드
item.ebwizardry\:warlock_robe_healing.name=치유주술사 로브
item.ebwizardry\:warlock_leggings_healing.name=치유주술사 각반
item.ebwizardry\:warlock_boots_healing.name=치유주술사 부츠
item.ebwizardry\:spawn_wizard.name=생성: 마법사
item.ebwizardry\:spawn_evil_wizard.name=생성: 사악한 마법사
@@ -538,7 +538,7 @@ item.ebwizardry\:charm_flight.name=에메랄드 딱정벌레 날개
item.ebwizardry\:charm_flight.desc=비행 및 활공 속도가 50%%더 빨라집니다
item.ebwizardry\:charm_growth.name=마법수정 꽃 부적
item.ebwizardry\:charm_growth.desc=수확의 축복 주문이 35%%확률로 식물을 완전히 자라게 합니다
item.ebwizardry\:charm_abseiling.name=마법이 부여된 실타래
item.ebwizardry\:charm_abseiling.name=마법이 부여된 실뭉치
item.ebwizardry\:charm_abseiling.desc=덩굴의 얽매임을 사용하며 공중에 있을 때 웅크리면 덩굴의 길이가 늘어납니다
item.ebwizardry\:charm_silk_touch.name=월광석 보주
item.ebwizardry\:charm_silk_touch.desc=채광 주문에 섬세한 손길이 적용됩니다
@@ -850,8 +850,8 @@ advancement.ebwizardry\:sage=학자의 길
advancement.ebwizardry\:sage.desc=학자의 갑옷을 획득하세요
advancement.ebwizardry\:battlemage=전투법사의 서약
advancement.ebwizardry\:battlemage.desc=전투법사의 갑옷을 획득하세요
advancement.ebwizardry\:warlock=워록의 방식
advancement.ebwizardry\:warlock.desc=워록의 갑옷을 획득하세요
advancement.ebwizardry\:warlock=주술사의 방식
advancement.ebwizardry\:warlock.desc=주술사의 갑옷을 획득하세요
advancement.ebwizardry\:enchant_scroll=두루마리!
advancement.ebwizardry\:enchant_scroll.desc=빈 두루마리를 만들고 신비로운 작업대에서 주문의 마법을 부여하세요
@@ -52,8 +52,8 @@ tile.ebwizardry\:dark_oak_lectern.name=Кафедра из тёмного дуб
tile.ebwizardry\:receptacle.name=Вместилище
tile.ebwizardry\:imbuement_altar.name=Алтарь наполнения
item.ebwizardry\:crystal_magic.name=Магический кристалл
item.ebwizardry\:crystal_magic.desc=Переливающиеся цвета этого кристалла, кажется, медленно меняются и кружатся, намекая на магическую энергию внутри. Возможно, эту магию можно задействовать, как-нибудь...
item.ebwizardry\:crystal_magic.name=Волшебный кристалл
item.ebwizardry\:crystal_magic.desc=Переливающиеся цвета этого кристалла, кажется, медленно меняются и кружатся, намекая на волшебную энергию внутри. Возможно, эту магию можно задействовать, как-нибудь...
item.ebwizardry\:crystal_fire.name=Огненный кристалл
item.ebwizardry\:crystal_fire.desc=Кристалл, который светится оранжево-огненным цветом. Возможно, он - ключ к разблокировки элемента огня...
item.ebwizardry\:crystal_ice.name=Ледяной кристалл
@@ -96,7 +96,7 @@ item.ebwizardry\:wand.levelup=%1$s готов улучшиться до уров
item.ebwizardry\:wand.addally=%1$s был добавлен в Ваш список союзников.
item.ebwizardry\:wand.removeally=%1$s был убран из Вашего списка союзников.
item.ebwizardry\:magic_wand.name=Магический жезл
item.ebwizardry\:magic_wand.name=Волшебный жезл
item.ebwizardry\:apprentice_wand.name=Жезл ученика
item.ebwizardry\:advanced_wand.name=Продвинутый жезл
item.ebwizardry\:master_wand.name=Жезл мастера
@@ -145,10 +145,10 @@ item.ebwizardry\:medium_mana_flask.name=Средняя колба с маной
item.ebwizardry\:large_mana_flask.name=Большая колба с маной
item.ebwizardry\:mana_flask.desc=Изготовьте колбу с маной с использованием Жезла или части брони Волшебника, чтобы восстановить %s маны.
item.ebwizardry\:grand_crystal.name=Большой магический кристалл
item.ebwizardry\:grand_crystal.desc=Крупный магический кристалл, в несколько раз больше тех, что обнаружены естественным образом. Кто-то, видимо, вырастил его искусственно - но как?
item.ebwizardry\:crystal_shard.name=Магический кристальный осколок
item.ebwizardry\:crystal_shard.desc=Маленький кусочек раздробленного магического кристалла. Он содержит в себе немного кол-во маны, но он может иметь другое применение...
item.ebwizardry\:grand_crystal.name=Большой волшебный кристалл
item.ebwizardry\:grand_crystal.desc=Крупный волшебный кристалл, в несколько раз больше тех, что обнаружены естественным образом. Кто-то, видимо, вырастил его искусственно - но как?
item.ebwizardry\:crystal_shard.name=Волшебный кристальный осколок
item.ebwizardry\:crystal_shard.desc=Маленький кусочек раздробленного волшебного кристалла. Он содержит в себе немного количество маны, но он может иметь другое применение...
item.ebwizardry\:astral_diamond.name=Звёздный алмаз
item.ebwizardry\:astral_diamond.desc=Высоко-ценившиеся драгоценный камень, который ярко сверкает над звёздным светом. Поговаривают, что самые могущественные Волшебники ищут Звёздные алмазы в замен, на самые неуловимые Таинственные знания.
@@ -176,7 +176,7 @@ item.ebwizardry\:range_upgrade.desc=Улучшает эффективный ра
item.ebwizardry\:duration_upgrade.desc=Улучшает продолжительность эффектов брошенным Жезлом.
item.ebwizardry\:cooldown_upgrade.desc=Улучшает скорость отката заклинания Жезла.
item.ebwizardry\:blast_upgrade.desc=Улучшает область эффекта заклинаний брошенным Жезлом.
item.ebwizardry\:attunement_upgrade.desc=Улучшает кол-во заклинаний, которых можно привязать к Жезлу.
item.ebwizardry\:attunement_upgrade.desc=Улучшает количество заклинаний, которых можно привязать к Жезлу.
item.ebwizardry\:melee_upgrade.desc=Улучшает жезл на использование маны, для нанесения большего урона по мобам, при ударе.
item.ebwizardry\:flaming_axe.name=Пылающий топор
@@ -204,7 +204,7 @@ item.ebwizardry\:armour_upgrade.name=Мистическая печать защ
item.ebwizardry\:armour_upgrade.desc=Улучшает любую Броню волшебника, чтобы сделать её %1$s Легендарной.
item.ebwizardry\:armour_upgrade.desc_extended=Примените это Улучшение в часть брони Волшебника в Мистическом верстаке.
item.ebwizardry\:magic_silk.name=Магический шёлк
item.ebwizardry\:magic_silk.name=Волшебный шёлк
item.ebwizardry\:spectral_dust.name=Спектральный прах
@@ -274,7 +274,7 @@ item.ebwizardry\:ring_condensing.desc=Медленно восстанавлив
item.ebwizardry\:ring_siphoning.name=Кольцо выкачивания
item.ebwizardry\:ring_siphoning.desc=Увеличивает выкачивание маны на 30%%.
item.ebwizardry\:ring_battlemage.name=Кольцо боевого мага
item.ebwizardry\:ring_battlemage.desc=Удерживая жезл в левой руке и меч в основной руке, даёт 10%% дополнительного магического урона.
item.ebwizardry\:ring_battlemage.desc=Удерживая жезл в левой руке и меч в основной руке, даёт 10%% дополнительного волшебного урона.
item.ebwizardry\:ring_combustion.name=Кольцо горения
item.ebwizardry\:ring_combustion.desc=Существа, убитые Огненными заклинаниями, взрываются.
item.ebwizardry\:ring_fire_melee.name=Кольцо огненного прикосновения
@@ -339,7 +339,7 @@ item.ebwizardry\:ring_interdiction.desc=Ваше силовое поле пов
item.ebwizardry\:amulet_arcane_defence.name=Амулет мистической защиты
item.ebwizardry\:amulet_arcane_defence.desc=Медленно восстанавливается мана на всю одетую броню Волшебника.
item.ebwizardry\:amulet_warding.name=Амулет защиты
item.ebwizardry\:amulet_warding.desc=Сокращает весь входящий магический урон на 10%%.
item.ebwizardry\:amulet_warding.desc=Сокращает весь входящий волшебный урон на 10%%.
item.ebwizardry\:amulet_wisdom.name=Амулет мудрости
item.ebwizardry\:amulet_wisdom.desc=Существенно сокращает шанс отрицательных эффектов при использовании неоткрытых Заклинаний.
item.ebwizardry\:amulet_fire_protection.name=Амулет быстрой пламени
@@ -591,7 +591,7 @@ 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\:magic_slime.name=Волшебный слизень
entity.ebwizardry\:silverfish_minion.name=Чешуйница
entity.ebwizardry\:storm_elemental.name=Грозовой элементаль
entity.ebwizardry\:evil_wizard.name=Злой волшебник
@@ -599,31 +599,31 @@ entity.ebwizardry\:decoy.name=Приманка
entity.ebwizardry\:vex_minion.name=Досаждатель
entity.ebwizardry\:remnant.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\:combustion_rune.name=Магическая
entity.ebwizardry\:flamecatcher_arrow.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\:combustion_rune.name=Волшебная
entity.ebwizardry\:flamecatcher_arrow.name=Волшебная
entity.ebwizardry\:black_hole.name=Чёрная дыра
entity.ebwizardry\:shield.name=Щит
@@ -652,9 +652,9 @@ itemGroup.ebwizardrygear=Снаряжение wizardry
advancement.ebwizardry\:root=Волшебство
advancement.ebwizardry\:root.desc=Путешествие волшебника к освоению Мистики.
advancement.ebwizardry\:crystal=Любопытный кристалл...
advancement.ebwizardry\:crystal.desc=Добудьте магический кристалл.
advancement.ebwizardry\:crystal.desc=Добудьте волшебный кристалл.
advancement.ebwizardry\:arcane_initiate=Приступить к Мистике.
advancement.ebwizardry\:arcane_initiate.desc=Создайте магический Жезл из Золотого самородка, Палки и Магического кристалла.
advancement.ebwizardry\:arcane_initiate.desc=Создайте волшебный Жезл из Золотого самородка, Палки и Волшебного кристалла.
advancement.ebwizardry\:apprentice=Ученик волшебника.
advancement.ebwizardry\:apprentice.desc=Используйте фолиант арканы, чтобы улучшить свой жезл.
@@ -665,13 +665,13 @@ advancement.ebwizardry\:advanced.desc=Улучшите свой Жезл до П
advancement.ebwizardry\:master=Мастер в Мистике.
advancement.ebwizardry\:master.desc=Получите жезл мастера.
advancement.ebwizardry\:max_out_wand=Полностью оборудован.
advancement.ebwizardry\:max_out_wand.desc=Примените максимальное кол-во улучшений в жезл Мастера.
advancement.ebwizardry\:max_out_wand.desc=Примените максимальное количество улучшений в жезл Мастера.
advancement.ebwizardry\:all_spells=Маг на все руки.
advancement.ebwizardry\:all_spells.desc=Бросьте каждое Заклинание в игре.
advancement.ebwizardry\:wizard_tower=Кто здесь живёт?
advancement.ebwizardry\:wizard_tower.desc=Посетите башню Волшебника.
advancement.ebwizardry\:wizard_trade=Магическое решение.
advancement.ebwizardry\:wizard_trade=Волшебное решение.
advancement.ebwizardry\:wizard_trade.desc=Купите предмет у Волшебника.
advancement.ebwizardry\:anger_wizard=Вы пожалеете об этом.
advancement.ebwizardry\:anger_wizard.desc=Разозлите волшебника.
@@ -815,7 +815,7 @@ spell.ebwizardry\:disintegration=Распад
spell.ebwizardry\:divination=Предсказание
spell.ebwizardry\:dragon_fireball=Огненный шар дракона
spell.ebwizardry\:earthquake=Землятресение
spell.ebwizardry\:empowering_presence=Магическое усиление
spell.ebwizardry\:empowering_presence=Волшебное усиление
spell.ebwizardry\:enrage=Разозление
spell.ebwizardry\:entrapment=Провокация
spell.ebwizardry\:evade=Уклонение
@@ -888,7 +888,7 @@ spell.ebwizardry\:lightning_pulse=Молниевый пульс
spell.ebwizardry\:lightning_ray=Молниевый луч
spell.ebwizardry\:lightning_sigil=Молниевый сигил
spell.ebwizardry\:lightning_web=Молниевая паутина
spell.ebwizardry\:magic_missile=Магический снаряд
spell.ebwizardry\:magic_missile=Волшебный снаряд
spell.ebwizardry\:mark_sacrifice=Знак жертвоприношения
spell.ebwizardry\:metamorphosis=Метаморфоз
spell.ebwizardry\:meteor=Метеор
@@ -983,7 +983,7 @@ spell.ebwizardry\:chain_lightning.desc=Стреляет искрами свет
spell.ebwizardry\:charge.desc=Заставляет заклинателя стремительно заряжаться в том направлении, куда он смотрит, повреждая и отбрасывая всё на своём пути.
spell.ebwizardry\:clairvoyance.desc=Раскрывает путь в запоминающее место. С этим выбранным заклинанием, shift + пкм по блоку, чтобы задать место. Бросьте это Заклинание как обычно, чтобы раскрыть путь. Путь исчезнет через 90 секунд.
spell.ebwizardry\:cobwebs.desc=Создаёт паутины туда, куда Вы указываете, она-же, сильно сдерживают движение любых существ пойманные среди них. Паутины пропадут через 20 секунд либо если сломать.
spell.ebwizardry\:combustion_rune.desc=Помещает магические наземные мины на землю туда, куда Вы указываете, которые взрываются когда ступите на них.
spell.ebwizardry\:combustion_rune.desc=Помещает волшебные наземные мины на землю туда, куда Вы указываете, которые взрываются когда ступите на них.
spell.ebwizardry\:conjure_armour.desc=Создаёт спектральную броню вокруг Заклинателя, обеспечивающая защиту равной по защите Железной брони. Броня длится 60 секунд. У заклинателя должен быть Пустой слот для брони.
spell.ebwizardry\:conjure_block.desc=Призывает спектральный блок туда, куда Вы указываете. Спектральный блок исчезает через 45 секунд, или Вы можете устранить его, снова бросив на него Заклинание.
spell.ebwizardry\:conjure_bow.desc=Создаёт спектральный лук с безграничными стрелами, которые длятся 60 секунд.
@@ -1005,7 +1005,7 @@ spell.ebwizardry\:disintegration.desc=Выстреливает мощной мо
spell.ebwizardry\:divination.desc=Направляет заклинателя к близлежащим Рудам и Ресурсам. Мощь, увеличит вероятность найти больше ценных руд.
spell.ebwizardry\:dragon_fireball.desc=Запускает огненный шар дракона в направлении, по которому Вы указываете, который выпускает сохраняющиеся Отравляющие облака при попадании.
spell.ebwizardry\:earthquake.desc=Истинный мастер земной магии, который может сдвинуть горы.
spell.ebwizardry\:empowering_presence.desc=Даёт Заклинателю и ближайшим Союзникам усиленный магический урон на 30 секунд.
spell.ebwizardry\:empowering_presence.desc=Даёт Заклинателю и ближайшим Союзникам усиленный волшебный урон на 30 секунд.
spell.ebwizardry\:enrage.desc=Причиняет близлежащих существ впадать в ярость, вместо этого, останавливая всё, что они делали напасть на Заклинателя.
spell.ebwizardry\:entrapment.desc=Заманивает цель в Сферу тьмы, которая беспомощно тянет её вверх и непрерывно повреждает её.
spell.ebwizardry\:evade.desc=Заставляет заклинателя быстро отпрыгнуть в сторону, чтобы увернуться от происходящих атак.
@@ -1014,7 +1014,7 @@ 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\:fire_sigil.desc=Помещает волшебную огненную ловушку на землю, которая повреждает и поджигает существо сдетонирующее её.
spell.ebwizardry\:fireskin.desc=Покрывает заклинателя в пламя на 30 секунд, причиняет всё, что атакует его загореться.
spell.ebwizardry\:firestorm.desc="Очистите землю и очистите почву!\nДеревья должны гореть, а озера должны кипеть!\nСпалите дерево и подпалите камень!\nВсем склониться перед адским троном!"
spell.ebwizardry\:fire_breath.desc="Я, дракон."
@@ -1023,26 +1023,26 @@ 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_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\:forest_of_thorns.desc=Посреди леса кроется скрытая поляна,\nВ поляне играет Волшебник,\nМагические искусства невыразимого порядка,\nГлубоко в лесу шипов.
spell.ebwizardry\:forest_of_thorns.desc=Посреди леса кроется скрытая поляна,\nВ поляне играет Волшебник,\nВолшебные искусства невыразимого порядка,\nГлубоко в лесу шипов.
spell.ebwizardry\:freeze.desc=Замораживает цель на 10 секунд. Также будет замораживать воду и создавать на земле снег.
spell.ebwizardry\:freezing_weapon.desc=Временно наполняет первое оружие в панели быстрого доступа Заклинателя силой мороза, причиняя замораживание жертв. Магия выветрится через 45 секунд.
spell.ebwizardry\:frost_axe.desc=Создаёт морозный топор, который замораживает врагов при ударе. Длится 30 секунд.
spell.ebwizardry\:frost_barrier.desc=Создаёт баррикаду льда впереди Заклинателя, которая ограждает их от поступающих атак. Барьер длится 20 секунд.
spell.ebwizardry\:frost_ray.desc=Создаёт поток мороза в направлении, по которому Вы указываете, который замедляет и регулярно повреждает цели.
spell.ebwizardry\:frost_sigil.desc=Помещает магическую ледяную ловушку на землю, которая повреждает и замораживает существо, сдетонирующее её.
spell.ebwizardry\:frost_sigil.desc=Помещает волшебную ледяную ловушку на землю, которая повреждает и замораживает существо, сдетонирующее её.
spell.ebwizardry\:frost_step.desc=Позволяет заклинателю замораживать воду пока он бродит, на 30 секунд.
spell.ebwizardry\:grapple.desc=Выстреливает магической лианой, которая позволяет Заклинателю захватываться в сторону блоков или сматывать существ. Отпустите лкм, чтобы освободить Блок или Существо.
spell.ebwizardry\:grapple.desc=Выстреливает волшебной лианой, которая позволяет Заклинателю захватываться в сторону блоков или сматывать существ. Отпустите лкм, чтобы освободить Блок или Существо.
spell.ebwizardry\:glide.desc=При удержании Лкм, позволяет Заклинателю скользить вниз, пока он находится в воздухе.
spell.ebwizardry\:greater_fireball.desc=Запускает большой огненный шар в направлении, по которому Вы указываете, который врывается при попадании.
spell.ebwizardry\:greater_heal.desc=Излечивает заклинателя 4-мя сердцами.
spell.ebwizardry\:greater_telekinesis.desc=Позволяет заклинателю подбирать блок или существо и удерживать его в воздухе до тех пор, пока зажата кнопка Лкм. Shift во время удержания блока или существа, выбросит его на короткое расстояние.
spell.ebwizardry\:greater_ward.desc=Даёт заклинателю мощный защитный эффект, который существенно сокращает входящий магический урон на 30 секунд.
spell.ebwizardry\:greater_ward.desc=Даёт заклинателю мощный защитный эффект, который существенно сокращает входящий волшебный урон на 30 секунд.
spell.ebwizardry\:group_heal.desc=Лечит заклинателя и всех поблизости союзников, и, призывает существо с 3-мя сердцами.
spell.ebwizardry\:growth_aura.desc=Выращивает все посевы рядом от Заклинателя. Также выращивает высокую траву и цветы на блоке травы.
spell.ebwizardry\:guardian_beam.desc=Стреляет лучами из глаз Стража в направлении, по которому Вы указываете, который повреждает цели и истощает их запас воздуха под водой.
@@ -1069,17 +1069,17 @@ spell.ebwizardry\:ironflesh.desc=Существенно улучшает соп
spell.ebwizardry\:leap.desc=Заставляет заклинателя прыгать выше на несколько блоков и слегка вперёд.
spell.ebwizardry\:levitation.desc=Поднимает заклинателя вверх, пока зажата кнопка Лкм. Также будет сводить на нет урон от падения, если оно используется до удара об землю.
spell.ebwizardry\:life_drain.desc=Создаёт поток иссушительной энергии в направлении, по которому Вы указываете, которая высасывает жизнь из цели и использует её, чтобы мало-помалу восстановить Ваше здоровье.
spell.ebwizardry\:light.desc=Создаёт магическую точку света, которая освещает окружающую область. Длится 30 секунд.
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_sigil.desc=Размещает волшебную молниевую ловушку на землю, которая повреждает существо, сдетонирующее её и зацепит других поблизости существ.
spell.ebwizardry\:lightning_web.desc="Сконцентрируйтесь. Направьте шторм в свой разум сквозь Жезл и освободите свою ярость."
spell.ebwizardry\:magic_missile.desc=Стреляет молнией магической энергией в направлении, по которому Вы указываете.
spell.ebwizardry\:mark_sacrifice.desc=Помечает цель как божественную жертву. Следующая магическая атака на помеченного существа, нанесёт 60%% дополнительного урона с каждым уровнем эффекта.
spell.ebwizardry\:magic_missile.desc=Стреляет молнией волшебной энергией в направлении, по которому Вы указываете.
spell.ebwizardry\:mark_sacrifice.desc=Помечает цель как божественную жертву. Следующая волшебная атака на помеченного существа, нанесёт 60%% дополнительного урона с каждым уровнем эффекта.
spell.ebwizardry\:metamorphosis.desc=Преобразует цель в другую форму. Работает только на определённых существ.
spell.ebwizardry\:meteor.desc=Некоторые волшебники хотят увидеть, как горит мир...
spell.ebwizardry\:mind_control.desc=Берёт контроль над разумом цели на 30 секунд, заставив его поменяться местами и драться вместо Заклинателя. Не будет работать на существ, которые слишком сильны волей.
@@ -1099,12 +1099,12 @@ spell.ebwizardry\:pocket_workbench.desc=Позволяет заклинател
spell.ebwizardry\:poison.desc=Стреляет ядом в направлении, по которому Вы указываете.
spell.ebwizardry\:poison_bomb.desc=Запускает отравляющую бомбу в направлении, по которому Вы указываете, которая взрывается при попадании, а также отравляет ближайших существ.
spell.ebwizardry\:possession.desc="Стать своим врагом."
spell.ebwizardry\:radiant_totem.desc=Создаёт сияющий тотем, который выстреливает лучом света на поблизости существ, лечащий Союзников, но повреждает мобов. Длится 30 секунд. Мощь, повысит кол-во целей.
spell.ebwizardry\:radiant_totem.desc=Создаёт сияющий тотем, который выстреливает лучом света на поблизости существ, лечащий Союзников, но повреждает мобов. Длится 30 секунд. Мощь, повысит количество целей.
spell.ebwizardry\:ray_of_purification.desc=Испускает луч ослепительного света, который повреждает и слепит цели. Неживые существа получат 2-й урон и загорятся.
spell.ebwizardry\:remove_curse.desc=Снимает любое проклятие, которое на данный момент влияет на Заклинателя.
spell.ebwizardry\:replenish_hunger.desc=Восполняет уровень еды Заклинателя 3-мя очками голода.
spell.ebwizardry\:resurrection.desc=С мастером целителем рядом с Вами, быть мертвым... необязательно.
spell.ebwizardry\:reversal.desc=Снимает случайный отрицательный эффект зелья и наносит его на цель, который будет страдать от этого эффекта в течение оставшегося периода времени. Мощь, увеличивает кол-во эффектов, которые будут обращены.
spell.ebwizardry\:reversal.desc=Снимает случайный отрицательный эффект зелья и наносит его на цель, который будет страдать от этого эффекта в течение оставшегося периода времени. Мощь, увеличивает количество эффектов, которые будут обращены.
spell.ebwizardry\:ring_of_fire.desc=Создаёт кольцо огня вокруг Заклинателя, которое повреждает всех ближайших врагов и поджигает их.
spell.ebwizardry\:satiety.desc=Пополняет уровень еды Заклинателя 8-ю очками голода.
spell.ebwizardry\:shadow_ward.desc=Создаёт стену тьмы впереди Заклинателя, которая причиняет половину всего входящего урона наносимого нападающему.
@@ -1119,7 +1119,7 @@ spell.ebwizardry\:smoke_bomb.desc=Запускает дымовую бомбу
spell.ebwizardry\:snare.desc=Устанавливает ловушку на землю, которая повреждает и ненадолго замедляет существо, которое сдетонирует её.
spell.ebwizardry\:snowball.desc=Запускает снежок в направлении, по которому Вы указываете.
spell.ebwizardry\:spark_bomb.desc=Запускает шоковый заряд в направлении, по которому Вы указываете, который выпускает искры на ближайших врагов при попадании.
spell.ebwizardry\:spectral_pathway.desc=Создаёт несокрушимый магический мост впереди Вас, который расширяется на 15 блоков. Мост исчезнет через 1 минуту.
spell.ebwizardry\:spectral_pathway.desc=Создаёт несокрушимый волшебный мост впереди Вас, который расширяется на 15 блоков. Мост исчезнет через 1 минуту.
spell.ebwizardry\:speed_time.desc=...день, ночь, рассвет, сумерки, восход и закат\: таким образом, проходит время, которое охватывает нас в бесконечном цикле...
spell.ebwizardry\:spider_swarm.desc=Призывает рой ядовитых пауков сражающихся за Вас. Пауки пропадут через 30 секунд, либо если их убьют.
spell.ebwizardry\:static_aura.desc=Окружает заклинателя молнией на 30 секунд, стреляя искрами молнии во что-либо, кто ударит его.
@@ -1148,7 +1148,7 @@ spell.ebwizardry\:transportation.desc=Перемещает заклинател
spell.ebwizardry\:vanishing_box.desc=Даёт заклинателю доступ к хранилищу Сундуку края.
spell.ebwizardry\:vex_swarm.desc=Призывает рой летающих досаждателей сражающихся за Вас. Досаждатели пропадут через 30 секунд, либо если их убьют.
spell.ebwizardry\:wall_of_frost.desc=Зима в Ваших пальцах.
spell.ebwizardry\:ward.desc=Даёт заклинателю защитный эффект, который снижает входящий магический урон на 30 секунд.
spell.ebwizardry\:ward.desc=Даёт заклинателю защитный эффект, который снижает входящий волшебный урон на 30 секунд.
spell.ebwizardry\:water_breathing.desc=Позволяет заклинателю дышать под водой на 1 минуту.
spell.ebwizardry\:whirlwind.desc=Заставляет цель взлетать вверх и подальше от Вас на скорости.
spell.ebwizardry\:wither.desc=Стреляет лучом тьмы, которая иссушает всё, что прикоснётся.
@@ -1269,7 +1269,7 @@ enchantment.ebwizardry\:flaming_weapon=Наполнение огнём
enchantment.ebwizardry\:freezing_weapon=Наполнение морозом
enchantment.ebwizardry\:shocking_weapon=Наполнение молнией
enchantment.ebwizardry\:magic_protection=Магическая защита
enchantment.ebwizardry\:magic_protection=Волшебная защита
enchantment.ebwizardry\:frost_protection=Морозная защита
enchantment.ebwizardry\:shock_protection=Шоковая защита
@@ -1279,7 +1279,7 @@ enchantment.ebwizardry.flaming_weapon.desc=Часть заклинания Ог
enchantment.ebwizardry.freezing_weapon.desc=Часть заклинания Замороженного оружия; недостижимо в режиме Выживания (книга не сработает).
enchantment.ebwizardry.shocking_weapon.desc=Часть заклинания Шокирующего оружия; недостижимо в режиме Выживания (книга не сработает).
enchantment.ebwizardry.magic_protection.desc=Уменьшает весь магический урон.
enchantment.ebwizardry.magic_protection.desc=Уменьшает весь волшебный урон.
enchantment.ebwizardry.frost_protection.desc=Уменьшает урон от заморозки.
enchantment.ebwizardry.shock_protection.desc=Уменьшает урон от шока.
@@ -1336,6 +1336,8 @@ commands.ebwizardry\:discoverspell.removespell=Убрано %1$s из данны
config.ebwizardry.title.general=Параметры мода
config.ebwizardry.redundant_keys=В Вашем файле конфигурации содержатся лишние параметры, они ничего не сделают! [Подробности см. В журнале]
config.ebwizardry.generic.true=Вкл
config.ebwizardry.generic.false=Выкл
@@ -1463,9 +1465,9 @@ config.ebwizardry.bookshelf_blocks.tooltip=Список названий бло
config.ebwizardry.book_items=Книги
config.ebwizardry.book_items.tooltip=Список названий предметов в реестре, которых можно поместить в Книжную полку, в дополнение к стандартным. Названия предметов не чувствительны к регистру. Для предметов мода, префикс с ID мода (например: thaumcraft:thaumonomicon).
config.ebwizardry.bookshelf_search_radius=Радиус поиска Книжной полки
config.ebwizardry.bookshelf_search_radius.tooltip=Максимальное кол-во блоков может быть в Книжной полке из Мистического верстака или Кафедры, чтобы иметь возможность соединиться к ней.
config.ebwizardry.bookshelf_search_radius.tooltip=Максимальное количество блоков может быть в Книжной полке из Мистического верстака или Кафедры, чтобы иметь возможность соединиться к ней.
config.ebwizardry.currency_items=Предметы валюты
config.ebwizardry.currency_items.tooltip=Список названий предметов в реестре, который торгующийся Волшебник может использовать в качестве Валюты (в первом слоте; второй слот не затрагивается). Каждая запись в этом списке должна содержать название предмета в реестре, с последующим одним местом, затем целое число, определяющее 'значение' предмета. Более высокие значения означают, что требуется меньшее кол-во Валютных предметов для получения торговли.
config.ebwizardry.currency_items.tooltip=Список названий предметов в реестре, который торгующийся Волшебник может использовать в качестве Валюты (в первом слоте; второй слот не затрагивается). Каждая запись в этом списке должна содержать название предмета в реестре, с последующим одним местом, затем целое число, определяющее 'значение' предмета. Более высокие значения означают, что требуется меньшее количество Валютных предметов для получения торговли.
config.ebwizardry.category.worldgen=Настройки генерации мира
config.ebwizardry.category.worldgen.tooltip=Настройте возможности генерации мира Wizardry
@@ -1630,9 +1632,9 @@ integration.antiqueatlas.marker.ebwizardry.obelisk=Обелиск
integration.antiqueatlas.marker.ebwizardry.shrine=Святилища
integration.antiqueatlas.marker.ebwizardry.library_ruins=Разрушенная библиотека
spell.ebwizardry\:magic_missile_festive=Магическая омела
spell.ebwizardry\:magic_missile_festive=Волшебная омела
spell.ebwizardry\:summon_snow_golem_festive=Призывает замороженного Снеговика
spell.ebwizardry\:invigorating_presence_festive=Бодрое усиление
spell.ebwizardry\:empowering_presence_festive=Магическое усиление
spell.ebwizardry\:empowering_presence_festive=Волшебное усиление
wizard.debug=%1$s, %2$s, %3$s.
@@ -363,6 +363,7 @@
"spell.zombie_apocalypse.start": {"category": "spells", "sounds": ["ebwizardry:dark_aura_start"]},
"spell.zombie_apocalypse.loop": {"category": "spells", "sounds": ["ebwizardry:dark_aura_loop"]},
"spell.zombie_apocalypse.end": {"category": "spells", "sounds": ["ebwizardry:dark_aura_end"]},
"spell.mirage": {"category": "spells", "sounds": ["ebwizardry:buff"]},
"forfeit.burn_self": {"category": "spells", "sounds": ["fire/ignite"]},
"forfeit.fireball": {"category": "spells", "sounds": ["mob/ghast/fireball4"]},
@@ -409,4 +410,4 @@
"forfeit.weaken_self": {"category": "spells", "sounds": ["mob/guardian/curse"]},
"forfeit.jam_self": {"category": "spells", "sounds": ["ebwizardry:effect1", "ebwizardry:effect2"]},
"forfeit.curse_self": {"category": "spells", "sounds": ["mob/guardian/curse"]}
}
}
@@ -17,7 +17,7 @@
"chargeup": 25,
"cooldown": 300,
"base_properties": {
"resistance_duration": 600,
"resistance_strength": 2
"diamondflesh_duration": 600,
"diamondflesh_strength": 0
}
}
@@ -14,11 +14,12 @@
"element": "healing",
"type": "buff",
"cost": 30,
"chargeup": 0,
"chargeup": 20,
"cooldown": 60,
"base_properties": {
"effect_radius": 5,
"effect_duration": 900,
"effect_strength": 1
"effect_strength": 0,
"potency_per_level": 0.15
}
}
@@ -17,7 +17,7 @@
"chargeup": 15,
"cooldown": 100,
"base_properties": {
"resistance_duration": 600,
"resistance_strength": 1
"ironflesh_duration": 600,
"ironflesh_strength": 0
}
}
@@ -17,7 +17,7 @@
"chargeup": 0,
"cooldown": 50,
"base_properties": {
"resistance_duration": 600,
"resistance_strength": 0
"oakflesh_duration": 600,
"oakflesh_strength": 0
}
}
@@ -20,6 +20,7 @@
"range": 10,
"damage": 4,
"effect_duration": 100,
"critical_health": 4
"critical_health": 4,
"player_effect_duration_multiplier": 0.5
}
}
@@ -18,6 +18,6 @@
"cooldown": 400,
"base_properties": {
"effect_radius": 8,
"wait_time": 300
"wait_time": 200
}
}
@@ -17,6 +17,8 @@
"chargeup": 20,
"cooldown": 400,
"base_properties": {
"minion_lifetime": 600,
"minion_count": 1,
"summon_radius": 2
}
}
@@ -70,6 +70,15 @@
"width": 90,
"height": 90
},
"classes": {
"location": "ebwizardry:textures/gui/handbook/pictures/classes.png",
"caption": "3가지 분야",
"u": 0,
"v": 0,
"width": 96,
"height": 32,
"border": false
},
"obelisk": {
"location": "ebwizardry:textures/gui/handbook/pictures/obelisk.png",
"caption": "방첨탑",
@@ -479,6 +488,7 @@
"wizard_armour": {
"title": "마법사의 갑옷",
"include_in_contents": "main_contents",
"triggers": [
"ebwizardry:arcane_initiate"
@@ -501,10 +511,24 @@
"아주 특별한 마법사들은 특정 원소에 영향을 주는 특별한 옷을 입는다네. 그 특별한 마법사의 갑옷은 찾기가 쉽지 않다네.",
"전설등급의 갑옷은 강력한 마법사들이 갑옷의 방어력을 크게 향상시키기 위해 사용하는 불가사의한 도장이 찍힌 갑옷을 말한다네."
"마법의 기본을 터득한 후에는 많은 마법사들이 훈련을 하기 위해 특별한 경로를 따라가거나 분야를 선택하게 된다네. 가장 주된 분야로는 학자와 전투법사 , 주술사 총 3가지가 있다네. 각 분야의 로브는 특이한 외형과 특성을 가지고 있는데 각 분야의 마법사들을 쉽게 구별하고 각 분야의 목적에 맞추기 위해 희귀하고 특이한 재료로 로브를 변형하였기 때문이라네. ",
"#image classes",
"학자",
"지식을 추구하기 위해 삶을 바치면서, 학자는 완벽하게 효율적인 시전 방법을 연구하여 , 가능한 한 적은 양의 마나를 사용하여 마법을 시전할 수 있게 됐다네. 학자의 비단 로브의 화려함에는 상당한 보호 기능이 있다네. 학자는 뛰어난 마법 부여로 실력으로 로브에 마법을 부여하기 때문이네. 그러나 이 비단 로브는 고체 금속을 도금한 갑옷과는 비교가 되지도 않는다네. 그리고 안전한 도서관에서 긴 시간을 보내는 학자의 특성상 전투에 더욱더 더디게 만드는 데 한몫했을걸세",
"전투법사",
"전투법사의 로브는 가장 뛰어난 대장간에서 만든 은도금된 수정과 견고한 천을 함께 사용하여 만든 전투용 로브라네. 전투법사는 단련과 수련을 통해 속도와 반응속도를 향상하여 주문을 더 자주 시전한다네. 그러나 전투법사는 결코 마나의 소모가 적지 않다네. 마나를 너무 빨리 소모하지 않도록 주의해야 할걸세.",
"주술사",
"주술사는 잃어버린 신비로운 비밀을 찾아낼 수 있는 경계를 넓히는 탐험을 하며 살아간다네. 또한, 그들은 다른 마법사들이 금지되었다고 말하는 실험을 진행하려 한다네. 전통적인 훈련의 제약을 깨부숴, 주문의 마나 사용량과 재사용 대기시간을 효과적으로 줄였다네. 주술사의 가벼운 로브는 비록 탐험에는 좋지만, 전투복보다는 보호받지 못할 걸세."
]
},
"magical_world": {
"title": "마법의 세계",
"include_in_contents": "main_contents",
@@ -11,8 +11,7 @@
"images": {
"workbench": {
"location":
"ebwizardry:textures/gui/handbook/pictures/arcane_workbench.png",
"location": "ebwizardry:textures/gui/handbook/pictures/arcane_workbench.png",
"caption": "Мистический верстак",
"u": 0,
"v": 0,
@@ -20,8 +19,7 @@
"height": 110
},
"crystal_ore": {
"location":
"ebwizardry:textures/gui/handbook/pictures/crystal_ore.png",
"location": "ebwizardry:textures/gui/handbook/pictures/crystal_ore.png",
"caption": "Кристальная руда",
"u": 0,
"v": 0,
@@ -30,7 +28,7 @@
},
"magic_crystal": {
"location": "ebwizardry:textures/items/crystal_magic.png",
"caption": "Магический кристалл",
"caption": "Волшебный кристалл",
"u": 6,
"v": 6,
"width": 36,
@@ -41,7 +39,7 @@
},
"magic_wand": {
"location": "ebwizardry:textures/items/wand_novice.png",
"caption": "Магический жезл",
"caption": "Волшебный жезл",
"u": 0,
"v": 0,
"width": 64,
@@ -49,8 +47,7 @@
"border": false
},
"crystal_flower": {
"location":
"ebwizardry:textures/gui/handbook/pictures/crystal_flower.png",
"location": "ebwizardry:textures/gui/handbook/pictures/crystal_flower.png",
"caption": "Кристальный цветок",
"u": 0,
"v": 0,
@@ -58,8 +55,7 @@
"height": 48
},
"wizard_tower": {
"location":
"ebwizardry:textures/gui/handbook/pictures/wizard_tower.png",
"location": "ebwizardry:textures/gui/handbook/pictures/wizard_tower.png",
"caption": "Башня волшебника",
"u": 0,
"v": 0,
@@ -67,17 +63,24 @@
"height": 110
},
"wizard_armour": {
"location":
"ebwizardry:textures/gui/handbook/pictures/wizard_armour.png",
"location": "ebwizardry:textures/gui/handbook/pictures/wizard_armour.png",
"caption": "Набор брони Волшебника",
"u": 0,
"v": 0,
"width": 90,
"height": 90
},
"classes": {
"location": "ebwizardry:textures/gui/handbook/pictures/classes.png",
"caption": "3 Класса",
"u": 0,
"v": 0,
"width": 96,
"height": 32,
"border": false
},
"obelisk": {
"location":
"ebwizardry:textures/gui/handbook/pictures/obelisk.png",
"location": "ebwizardry:textures/gui/handbook/pictures/obelisk.png",
"caption": "Обелиск",
"u": 0,
"v": 0,
@@ -85,8 +88,7 @@
"height": 67
},
"shrine": {
"location":
"ebwizardry:textures/gui/handbook/pictures/shrine.png",
"location": "ebwizardry:textures/gui/handbook/pictures/shrine.png",
"caption": "Святилище земли",
"u": 0,
"v": 0,
@@ -102,8 +104,7 @@
"height": 57
},
"remnant": {
"location":
"ebwizardry:textures/gui/handbook/pictures/remnant.png",
"location": "ebwizardry:textures/gui/handbook/pictures/remnant.png",
"caption": "Огненный пережиток",
"u": 0,
"v": 0,
@@ -111,9 +112,8 @@
"height": 73
},
"tiers": {
"location":
"ebwizardry:textures/gui/handbook/pictures/tiers.png",
"caption": "4 уровней жезла",
"location": "ebwizardry:textures/gui/handbook/pictures/tiers.png",
"caption": "4 уровня жезла",
"u": 0,
"v": 0,
"width": 96,
@@ -121,8 +121,7 @@
"border": false
},
"elements": {
"location":
"ebwizardry:textures/gui/handbook/pictures/elements.png",
"location": "ebwizardry:textures/gui/handbook/pictures/elements.png",
"caption": "7 мистических аспектов",
"u": 0,
"v": 0,
@@ -305,7 +304,7 @@
"title": "Введение",
"text": [
"Приветствую Вас, волшебник! Эта книга объясняет множество путей мистики и как их использовать. Эта не обычная книга, тем не менее - её страницы будут осуществляться перед Вами, когда Вы узнаете больше о Магическом мире.",
"Приветствую тебя, Волшебник! Эта книга объясняет множество путей мистики и как их использовать. Эта не обычная книга, тем не менее - её страницы будут осуществляться перед Вами, когда Вы узнаете больше о Волшебном мире.",
"Используйте кнопки Стрелок, чтобы переключаться между страницами, и кнопки с двойными стрелками, чтобы быстро перелистываться между разделами. Используйте центральную кнопку Меню, чтобы вернуться на основную страницу содержимого.",
@@ -328,9 +327,9 @@
"include_in_contents": "main_contents",
"text": [
"Чтобы начать в Wizardry, Вам понадобится:",
"Чтобы начать осваиваться в моём моде Wizardry, Вам понадобится:",
"- Магический жезл, создаётся как это показано:",
"- Волшебный жезл, создаётся как это показано:",
"#recipe magic_wand",
@@ -338,11 +337,11 @@
"#recipe arcane_workbench",
"- @spells Книга заклинаний@. Они могут быть найдены в сундуках, выпавшие как добыча, купленные у Волшебников, или Вы можете сделать Заклинание новичка: Магический метательный снаряд, как это показано:",
"- @spells Книга заклинаний@. Их можно найти в сундуках, выпавшие как добыча, купленные у Волшебников, или Вы можете сделать Заклинание новичка: Волшебный метательный снаряд, как это показано:",
"#recipe magic_missile_spell_book",
"Вам также нужно куча других Магических кристаллов, чтобы снабдить свой Жезл @mana маной@."
"Вам также нужно куча других Волшебных кристаллов, чтобы снабдить свой Жезл @mana маной@."
]
},
@@ -354,7 +353,7 @@
],
"text": [
"Мана - мистическая энергия, которая даёт Волшебникам их силы. Сама по себе она не физическая форма; скорее всего, она всегда присутствует в Ауре, которая проникает во всё в мире. В частности, она проявляется в Кристаллах, встречающихся в природе, которые могут быть найдены вложенными в камнях под землёй. @wands Жезлы@ могут хранить в себе Ману, и эта мана направляется в @spells Заклинания@, которых Вы можете бросить. Некоторые заклинания требуют некое кол-во маны, в зависимости от того, насколько они сильны и как долго они длятся.",
"Мана - мистическая энергия, которая даёт Волшебникам их силы. Сама по себе она не физическая форма; скорее всего, она всегда присутствует в Ауре, которая проникает во всё в мире. В частности, она проявляется в Кристаллах, встречающихся в природе, которые могут быть найдены вложенными в камнях под землёй. @wands Жезлы@ могут хранить в себе Ману, и эта мана направляется в @spells Заклинания@, которых Вы можете бросить. Некоторые заклинания требуют некое количество маны, в зависимости от того, насколько они сильны и как долго они длятся.",
"#image crystal_ore",
@@ -372,11 +371,11 @@
],
"text": [
"Жезл, это орудие выбора Волшебника. С ним Вы можете бросить любое @spells Заклинание@, если Жезл может сдерживать его силу (смотрите: @tiers Уровни@). Жезлы бывают разных видов, но Вы скорее всего приступите с простого Магического жезла.",
"Жезл, это орудие выбора Волшебника. С ним Вы можете бросить любое @spells Заклинание@, если Жезл может сдерживать его силу (смотрите: @tiers Уровни@). Жезлы бывают разных видов, но Вы скорее всего приступите с простого Волшебного жезла.",
"#image magic_wand",
"Большинство жезлов начинают свою жизнь как простое устройство своего рода Магического кристалла, прилагаемый к деревянной палке, с золотым самородком прикреплённый на другом конце. Кристалл это, разумеется, источник силы Жезла, поскольку он обеспечивает фокусировку, необходимая для направления @spells Заклинаний@. Оставшаяся часть Жезла тоже очень важна, поскольку она обеспечивает не только средства, с которыми держится Жезл, но также траектория, через которую @mana Ману@ можно направить и ориентировать.",
"Большинство жезлов начинают свою жизнь как простое устройство своего рода Волшебного кристалла, прилагаемый к деревянной палке, с золотым самородком прикреплённый на другом конце. Кристалл это, разумеется, источник силы Жезла, поскольку он обеспечивает фокусировку, необходимая для направления @spells Заклинаний@. Оставшаяся часть Жезла тоже очень важна, поскольку она обеспечивает не только средства, с которыми держится Жезл, но также траектория, через которую @mana Ману@ можно направить и ориентировать.",
"Чем больше заклинаний брошено Жезлом, тем больше он становится эффективным в направлении @spells Заклинаний@, и следовательно, может бросить заклинания большей силы. Этот эффект может быть различим по едва различимым изменениям, которые возникают в форме и внешнем виде самого Жезла: поскольку Жезл становится всё более мощным, его кристалл будет становиться всё более ярким, его цвет может изменяться в зависимости от его @elements Аспекта@, и спустя определённое время, дерево из которого он сделан, начнёт расти и меняться в более сложные формы.",
@@ -402,7 +401,7 @@
"Свитки весьма полезны, если Вам нужно использовать Заклинание один раз или дважды по конкретному заданию, чтобы не занимать место в слоте в своём @wands Жезле@. У них также имеется преимущество, мгновенно бросать Заклинания, которые обычно требуют период зарядки. Следует подчеркнуть, они являются неэффективным методом бросания Заклинаний по сравнению с использованием Жезла.",
"На первый взгляд, магические руны с помощью которых написаны Заклинания, нечитаемы. Для определения Заклинания, Вы можете, несомненно, бросить Заклинание и посмотреть, что произойдёт - хотя, это может вызвать нежеланные побочные последствия, и большинство Заклинаний нуждаются в определённых условиях для работы. Более того, всегда есть вероятность недооценить неизвестное Заклинание когда бросаете, с потенциально опасными последствиями в зависимости от того, насколько мощное Заклинание. Более безопасный и более надёжный вариант - использовать Свиток идентификации, который можно найти в сундуках или купить у Волшебника. Щёлкните Пкм, пока держите, Свиток идентифицирует первую неизвестную Книгу с заклинанием или Свиток в панели быстрого доступа, потребляя Свиток идентификации в процессе."
"На первый взгляд, волшебные руны с помощью которых написаны Заклинания, нечитаемы. Для определения Заклинания, Вы можете, несомненно, бросить Заклинание и посмотреть, что произойдёт - хотя, это может вызвать нежеланные побочные последствия, и большинство Заклинаний нуждаются в определённых условиях для работы. Более того, всегда есть вероятность недооценить неизвестное Заклинание когда бросаете, с потенциально опасными последствиями в зависимости от того, насколько мощное Заклинание. Более безопасный и более надёжный вариант - использовать Свиток идентификации, который можно найти в сундуках или купить у Волшебника. Щёлкните Пкм, пока держите, Свиток идентифицирует первую неизвестную Книгу с заклинанием или Свиток в панели быстрого доступа, потребляя Свиток идентификации в процессе."
]
},
@@ -448,7 +447,7 @@
],
"text": [
"Чтобы зарядить свой @wands Жезл@, поместите Жезл в центральный слот Мистического верстака и поместите несколько магических кристаллов в нижний левый слот, и затем нажмите Применить. Каждый кристалл стоит #mana_per_crystal @mana Маны@, и Жезл возьмёт столько, сколько ему необходимо, поэтому, Вы можете сохранить запасы кристаллов в Верстаке, когда они Вам понадобятся. Однако, имейте ввиду, что Жезл может взять только целое кол-во кристаллов, так что, если Жезлу необходимо, например, 30 и более маны, #example_charging_loss маны будет потеряно при зарядки."
"Чтобы зарядить свой @wands Жезл@, поместите Жезл в центральный слот Мистического верстака и поместите несколько волшебных кристаллов в нижний левый слот, и затем нажмите Применить. Каждый кристалл стоит #mana_per_crystal @mana Маны@, и Жезл возьмёт столько, сколько ему необходимо, поэтому, Вы можете сохранить запасы кристаллов в Верстаке, когда они Вам понадобятся. Однако, имейте ввиду, что Жезл может взять только целое количество кристаллов, так что, если Жезлу необходимо, например, 30 и более маны, #example_charging_loss маны будет потеряно при зарядки."
]
},
"upgrading_wands": {
@@ -472,7 +471,7 @@
],
"text": [
"Мистический верстак также может быть использован для Зачаровывания @spells заклинаний@ и Свитков. Для этого, Вам понадобится Пустой свиток, созданный из кусочка бумаги и несколько ниток, Книга с заклинанием выбранная для Заклинания, и достаточно магических кристаллов, чтобы предоставить @mana Ману@, для наложения.",
"Мистический верстак также может быть использован для Зачаровывания @spells заклинаний@ и Свитков. Для этого, Вам понадобится Пустой свиток, созданный из кусочка бумаги и несколько ниток, Книга с заклинанием выбранная для Заклинания, и достаточно волшебных кристаллов, чтобы предоставить @mana Ману@, для наложения.",
"#recipe blank_scroll",
@@ -490,11 +489,11 @@
],
"text": [
"Как волшебник, Вам нужно что-то, чтобы защитить Вас от существ, с которыми Вы сражаетесь. Впрочем, простая броня не подойдёт. Чтобы наиболее эффективно использовать свои Заклинания, Вам потребуется Броня волшебника: Шляпа, роба, поножи и ботинки. В отличие от простой брони, эти не ломаются. Вместо этого, они используют мистическую энергию для защиты Носителя. Это, безусловно, означает, что они могут быть заряжены Магическими кристаллами, точно также как Жезлы. К счастью, эта одежда не потребляет много @mana Маны@. Зарядите их, как Жезл в @arcane_workbench Мистическом верстаке@ или @mana_flasks Фляжками с маной@, но будьте осторожны - если у них кончится мана, то Вы окажетесь беззащитным.",
"Как волшебник, Вам нужно что-то, чтобы защитить Вас от существ, с которыми Вы сражаетесь. Впрочем, простая броня не подойдёт. Чтобы наиболее эффективно использовать свои Заклинания, Вам потребуется Броня волшебника: Шляпа, роба, поножи и ботинки. В отличие от простой брони, эти не ломаются. Вместо этого, они используют мистическую энергию для защиты Носителя. Это, безусловно, означает, что они могут быть заряжены Волшебными кристаллами, точно также как Жезлы. К счастью, эта одежда не потребляет много @mana Маны@. Зарядите их, как Жезл в @arcane_workbench Мистическом верстаке@ или @mana_flasks Фляжками с маной@, но будьте осторожны - если у них кончится мана, то Вы окажетесь беззащитным.",
"#image wizard_armour",
"Вы можете получить броню Волшебника создав её из Магического шёлка:",
"Вы можете получить броню Волшебника создав её из Волшебного шёлка:",
"#recipe magic_silk",
"#recipe wizard_hat",
@@ -502,11 +501,25 @@
"#recipe wizard_leggings",
"#recipe wizard_boots",
"Можно зачаровать Броню волшебника используя обычный Стол зачаровывания, а из-за собственных свойств магического шёлка, он довольно эффективен в сдерживании чар. Особенно полезны для Волшебников зачарования защиты - Магическая, Морозная и Шоковая, которая может оказаться полезной защитой против других обладателей магии.",
"Можно зачаровать Броню волшебника используя обычный Стол зачаровывания, а из-за собственных свойств волшебного шёлка, он довольно эффективен в сдерживании чар. Особенно полезны для Волшебников зачарования защиты - Волшебная, Морозная и Шоковая, которая может оказаться полезной защитой против других обладателей магии.",
"Те волшебники, кто посвящают себя практике одной стихии, иногда носят специальную одежду, которая даёт бонусы для этой стихии. Полный набор такой одежды очень востребованный среди Волшебников и её не так просто найти.",
"Легенда говорит о Мистической печати, используемой самыми могущественными Волшебниками, чтобы значительно улучшить свою броню."
"Как только они овладеют Основами магии, большинство Волшебников выберут следующий особый путь, либо класс, чтобы продолжить своё обучение. Есть 3 основных класса, к которым Волшебник может присоединиться: Мудрец, Боевой маг и Чародей. Членов каждого класса можно легко отличить по их мантиям, которые модифицируются - обычно с помощью Редких и Экзотических материалов - чтобы лучше удовлетворять свои потребности.",
"#image classes",
"Мудрец",
"Посвятив свою жизнь стремлению к знаниям, Мудрец усовершенствовал искусство эффективного бросания заклинания, позволив ему бросать заклинания используя наименьшее возможное количество маны. Их наряд из шёлковой мантии, опровергает значительную защиту, которую они обеспечивают, поскольку Мудрец также является искусным Волшебником - хотя они по-прежнему не могут сравниться с твёрдым металлическим покрытием. Однако, столь длительное проведение периодов времени в безопасной библиотеки делает их весьма вялыми в бою.",
"Боевой маг",
"Боевой маг является приспособленным для боя, одетого в комбинацию из упрочнённой ткани и кристально-серебряного покрытия добываемые на самых квалифицированных плавильных заводах. Через дисциплину и тренировку, боевой маг также улучшил свою скорость и реакции, позволяя ему более часто бросать заклинания. Однако, дёшево это не обходится, причём Боевой маг должен быть осторожен, чтобы слишком быстро не прожигать ману.",
"Чародей",
"Чародей живёт ради исследований, выталкивая границы того, что возможно, чтобы откапывать мистические тайны. Это, совместно со стремлением экспериментировать с тем, что другие могут счесть с запретным, позволили им преодолеть ограничения привычного обучения и бросать заклинания с невероятной скоростью, а также уменьшить использование маны. Их легковесные мантии, хотя и пригодны для разведки, обеспечивают меньшую защиту в бою, чем их представители. "
]
},
@@ -576,7 +589,7 @@
"#image obelisk",
"Эти структуры, как правило, защищены за счёт чар, которые призывают враждебных @creatures Магических существ@, если какой-нибудь человек случайно окажется поблизости. Отгоните этих существ и уничтожьте их источник, и реликвии будут Вашими."
"Эти структуры, как правило, защищены за счёт чар, которые призывают враждебных @creatures Волшебных существ@, если какой-нибудь человек случайно окажется поблизости. Отгоните этих существ и уничтожьте их источник, и реликвии будут Вашими."
]
},
"shrines": {
@@ -606,7 +619,7 @@
"#image library_ruins",
"Библиотеки не только используются для хранения книг. Волшебники прошлого, использовали силу Алтаря наполнения, который используется для осуществления наполнения магическими аспектами на магические материалы. Расположение алтаря является точным и сложным исскуством, поскольку, он должен быть соответствовать с учётом небесными движениями и местными колебаниями маны. Их практика строительства стала гораздо более редкой в новейшей истории, в основном, потому, что когда то построенный, твёрдый каменный алтарь держится веками, так что, нет особой обходимости в новых. Вместо этого, большинство Волшебников находят и восстанавливают существующий алтарь на случай того, чтобы необходимо было выполнять ритуалы для наполнения и, - Разрушенные библиотеки идеальное место для поиска.",
"Библиотеки не только используются для хранения книг. Волшебники прошлого, использовали силу Алтаря наполнения, который используется для осуществления наполнения волшебными аспектами на волшебные материалы. Расположение алтаря является точным и сложным исскуством, поскольку, он должен быть соответствовать с учётом небесными движениями и местными колебаниями маны. Их практика строительства стала гораздо более редкой в новейшей истории, в основном, потому, что когда то построенный, твёрдый каменный алтарь держится веками, так что, нет особой обходимости в новых. Вместо этого, большинство Волшебников находят и восстанавливают существующий алтарь на случай того, чтобы необходимо было выполнять ритуалы для наполнения и, - Разрушенные библиотеки идеальное место для поиска.",
"Вы, тоже, можете в определённый момент сочтить это полезным, и построить свою собственную библиотеку, которая, разумеется, потребует несколько Книжных полок:",
@@ -614,7 +627,7 @@
"#recipe gilded_wood",
"Однако, эти книжные полки не просто мебель. Наполняя самые мощные магические кристаллы в своих Книжных полках, позволит беспрепятственно передавать знания между ними и близлежащим @arcane_workbench Мистическим верстаком@ - очень удобно, когда коллекция расширяется. В равной степени полезна - Кафедра:",
"Однако, эти книжные полки не просто мебель. Наполняя самые мощные волшебные кристаллы в своих Книжных полках, позволит беспрепятственно передавать знания между ними и близлежащим @arcane_workbench Мистическим верстаком@ - очень удобно, когда коллекция расширяется. В равной степени полезна - Кафедра:",
"#recipe lecterns",
@@ -622,14 +635,14 @@
]
},
"creatures": {
"title": "Магические существа",
"title": "Волшебные существа",
"include_in_contents": "magical_world_subsections",
"triggers": [
"ebwizardry:handbook/magical_creatures"
],
"text": [
"Помимо волшебников, множество других существ также используют магию. Многие из этих существ загадочны по своему происхождению, и большую часть можно призвать используя конкретные магические @spells Заклинания@. Этих существ можно встретить охраняющих @obelisks Обелиск@, а может и мощного Призывателя. Менее загадочные существа периодически встречаются в глуши.",
"Помимо волшебников, множество других существ также используют магию. Многие из этих существ загадочны по своему происхождению, и большую часть можно призвать используя конкретные волшебные @spells Заклинания@. Этих существ можно встретить охраняющих @obelisks Обелиск@, а может и мощного Призывателя. Менее загадочные существа периодически встречаются в глуши.",
"Наглядным примером является Пережиток, наподобие духа, сущность, которая формируется естественным образом из вещества, которое остаётся за счёт мощной магии, и чаще всего, принимает 1 из 7 мистических @elements Аспектов@. По отдельности, они не более чем помеха, но толпа, может быстро ошеломить неподготовленного Искателя приключений, а их присущая устойчивость к магии, требует принятия разумного ношения с собой Лука, или другого оружия дальнего боя.",
@@ -650,7 +663,7 @@
],
"text": [
"Изучая @shrines Святилища@, возможно, Вам посчастливится обнаружить какой-нибудь древний магический артефакт - объект, способный предоставить своему Носителю уникальные и мощные баффы и особые силы. Известны 3 типа, которые были обнаружены: кольца, которые дают бонусы и эффекты к Заклинаниям, амулеты, которые увеличивают защитные свойства, и талисманы, которые дают полезные эффекты. Эти артефакты функционируют только в том случае, если надеть их правильным образом; просто имея их на одном человеке - недостаточно."
"Изучая @shrines Святилища@, возможно, Вам посчастливится обнаружить какой-нибудь древний волшебный артефакт - объект, способный предоставить своему Носителю уникальные и мощные баффы и особые силы. Известны 3 типа, которые были обнаружены: кольца, которые дают бонусы и эффекты к Заклинаниям, амулеты, которые увеличивают защитные свойства, и талисманы, которые дают полезные эффекты. Эти артефакты функционируют только в том случае, если надеть их правильным образом; просто имея их на одном человеке - недостаточно."
]
}
}
@@ -704,13 +717,13 @@
"#colour_earthЗемля#colour_reset \nАспект земли направлен на естественный мир: Животные, растения, ветер, и подобное. Магия земли разнообразная и принимает целый ряд форм, от отравления врагов до высвобождения ярости погоды. Заклинания земли - сочетание атаки, защиты и практичности.",
"#colour_sorceryВолшебство#colour_reset \nВолшебство является аспектом силы и разнообразия. Чародеи манипулируют светом, гравитацией и даже самой реальностью, для удовлетворения своих потребностей. Чародейские заклинания можно использовать, среди прочего, чтобы предоставить своему Заклинателю магические силы или двигать объекты по своей воле.",
"#colour_sorceryВолшебство#colour_reset \nВолшебство является аспектом силы и разнообразия. Чародеи манипулируют светом, гравитацией и даже самой реальностью, для удовлетворения своих потребностей. Чародейские заклинания можно использовать, среди прочего, чтобы предоставить своему Заклинателю волшебные силы или двигать объекты по своей воле.",
"#colour_healingЛечение#colour_reset \nАспект лечения соответствует защите и регенерации. Целители стараются защитить себя и своих союзников насколько это возможно, и связи с этим, могут быть весьма сложными соперниками. Хотя в целом, не используется как атака, очищающий свет некоторых исцеляющих Заклинаний, нанесёт немалый урон нежити. Лечебные заклинания незаменимы, когда в бою.",
"Границы между различными стихиями не всегда различаются, а некоторые Заклинания имеют схожие черты аспектов помимо их собственными.",
"Если Вам повезёт, Вы можете случайно встретить Стихийный кристалл. Стихийные кристаллы - магические кристаллы, которые поглощают стихийные свойства по мере своего роста - хотя точные необходимые условия и механизм, с помощью которых это происходит, остаётся загадкой. Нам известно, наверное, что подобные кристаллы можно использовать для создания стихийных Жезлов, которые позволяют бросать Заклинания с нужной стихией с большей мощью, чем обычно."
"Если Вам повезёт, Вы можете случайно встретить Стихийный кристалл. Стихийные кристаллы - волшебные кристаллы, которые поглощают стихийные свойства по мере своего роста - хотя точные необходимые условия и механизм, с помощью которых это происходит, остаётся загадкой. Нам известно, наверное, что подобные кристаллы можно использовать для создания стихийных Жезлов, которые позволяют бросать Заклинания с нужной стихией с большей мощью, чем обычно."
]
},
@@ -735,18 +748,18 @@
],
"text": [
"Arkendur's Arcane Supplies Co. - магические предметы для всех Ваших потребностей!",
"Arkendur's Arcane Supplies Co. - волшебные предметы для всех Ваших нужд!",
"Необходимо перезарядить свой @wands Жезл@ на ходу? Нет проблем! @mana Мана@ теперь может быть бутылированной. Просто создайте Фляжку с маной с помощью Колбы и 8 магическими кристаллами и заберите её с собой. Когда Вам нужно использовать её, просто создайте её с помощью своего Жезла и она восстановит немного заряда.*",
"Нужно перезарядить свой @wands Жезл@ на ходу? Нет проблем! @mana Ману@ теперь можно разливать в бутылки. Просто изготовьте Фляжку с маной с помощью Колбы и 8 волшебными кристаллами и заберите её с собой. Когда Вам нужно использовать её, просто изготовьте её своим Жезлом и она восстановит немного заряда.*",
"#recipe medium_mana_flask",
"НОВОЕ! Внедрение совершенно новых Малых и Больших фляжек с маной, и теперь - Вы можете выбрать размер Фляжки с маной, чтобы удовлетворить свои потребности!",
"НОВОЕ! Внедрение совершенно новых Малых и Больших фляжек с маной, а теперь - Вы можете выбрать размер Фляжки с маной, чтобы удовлетворять свои потребности!",
"#recipe small_mana_flask",
"#recipe large_mana_flask",
"* Этот процесс, уничтожит колбу. Некоторое кол-во маны потеряется во время разлива."
"* Этот процесс, уничтожит колбу. Определённое количество маны потеряется во время разлива."
]
},
"throwable_items": {
@@ -762,11 +775,7 @@
"#recipe firebomb",
"#recipe poison_bomb",
"#recipe smoke_bomb",
"#recipe spark_bomb",
"#recipe gilded_wood",
"#recipe bookshelves",
"#recipe lecterns",
"#recipe receptacle"
"#recipe spark_bomb"
]
},
"automated_casting": {
@@ -811,7 +820,11 @@
"#recipe firebomb",
"#recipe poison_bomb",
"#recipe smoke_bomb",
"#recipe spark_bomb"
"#recipe spark_bomb",
"#recipe gilded_wood",
"#recipe bookshelves",
"#recipe lecterns",
"#recipe receptacle"
]
},
@@ -832,11 +845,11 @@
"Код:",
"- Corail31 \n- 12foo \n- Shadows-of-Fire \n- HellFirePvP \n- Tora-B \n- Avatair \n- Aeronica \n- UltraHex \n- Azim-Palmer \n- raoulvdberge \n- rafasoares",
"- Corail31 \n- 12foo \n- Shadows-of-Fire \n- HellFirePvP \n- Tora-B \n- Avatair \n- Aeronica \n- UltraHex \n- Azim-Palmer \n- raoulvdberge \n- rafasoares \n- xinyuan-liu \n- SettingDust",
"Переводчики:",
"- Испанский: MadWrist, Alsentar \n- Мексиканский испанский: MadWrist \n- Русский: VilagVil, kellixon, bigenergy, DrHesperus \n- Французский: Hahdrim \n- Бразильский португальский: lorrampi \n- Китайский (Упрощённый): ZHENGLOC, dragon-evol, Hokorizero, TUsama, Determancer \n- Корейский: shejery, rewi_wire \n- Польский: Trozuu \n- Немецкий: BirdyDragon \n- Китайский (Традиционный): chesterccj305 \n- Венгерский: Bombadil",
"- Испанский: MadWrist, Alsentar \n- Мексиканский испанский: MadWrist \n- Русский: VilagVil, kellixon, bigenergy, MugGod2, DrHesperus \n- Французский: Hahdrim \n- Бразильский португальский: lorrampi \n- Китайский (Упрощённый): ZHENGLOC, dragon-evol, Hokorizero, TUsama, Determancer \n- Корейский: shejery, rewi_wire, 방통, red1854th \n- Польский: Trozuu, Olej \n- Немецкий: BirdyDragon, Lemopav \n- Китайский (Традиционный): chesterccj305 \n- Венгерский: Bombadil",
"Звуковые эффекты",
@@ -1,230 +0,0 @@
PAGEBREAK
LINEBREAK
Книга Волшебника
от Electroblob
PAGEBREAK
Введение
------------------------------
Приветствую вас, волшебник! Эта книга объясняет многие способы создания магии и способы ее использования.
Если вы когда-нибудь потеряете эту книгу, вы можете получить новую, соеденив книгу с магическим кристаллом.
PAGEBREAK
Содержание
------------------------------
PAGEBREAK
SECTION Начало
Начало
------------------------------
Чтобы начать работу с магией, вам понадобятся несколько вещей:
- Волшебный жезл, сделанный из золотого самородка, палки и магического кристалла.
- Чародейский стол, выполненный из 3 камней, 1 блока лазурита, 2 магических кристаллов, 2 золотых самородков и 1 фиолетового ковра.
- Книга заклинаний. Они могут быть найдены в сундуках, выбиты как дроп, куплены у волшебников, или вы можете сделать заклинание для новичка, магическую ракету, с книгой и 4 магическими кристаллами.
Вам также понадобится куча магических кристаллов, чтобы снабжать ваш жезл маной.
PAGEBREAK
SECTION Мана
Мана
------------------------------
Мана - это тайная энергия, которая дает волшебникам их силы. Она проявляется в встречающихся в природе кристаллах, которые можно обнаружить в подземных породах. Жезлы могут хранить ману, и эта мана направляется в заклинания, которые вы используете. Различные заклинания стоят разного количества маны, в зависимости от того, насколько они сильны и долговечны.
Наведите указатель мыши на жезл, чтобы увидеть, сколько маны хранится в нём.
LINEBREAK
IMAGE CRYSTAL
Магического
Руда Кристалл Кристалла
PAGEBREAK
SECTION Жезлы
Жезлы
------------------------------
Жезл - это инструмент для мастера. С его помощью вы можете использовать любое заклинание, если жезл может содержать его силу (см. Раздел «Уровни» для более подробного объяснения). Жезлов
различные варианты, но вы почти наверняка начнете с основного волшебного жезла.
Когда вы держите палочку, в углу экрана будет отображаться небольшой экран с заголовком. Это указывает на выбранное в настоящий момент заклинание вместе с изображением, и, если заклинание было использоно, кулдаун указывает время, до которого заклинание может быть снова использовано.
PAGEBREAK
SECTION Заклинания
Заклинания
------------------------------
Жезл бесполезен без заклинаний. Заклинания записываются в двух формах: в книгах, которые являются постоянными, и в свитках, которые являются временными.
Книги заклинаний мало нужны сами по себе; Вместо этого они используются для привязки заклинания, которое они содержат к жезлам. Книги заклинаний можно найти по всему миру, и вам не придется долго искать их. Когда вы её найдете, вы можете навести курсор мыши на книгу заклинаний, чтобы сразу увидеть основную информацию о заклинании. Вы также можете щелкнуть правой кнопкой мыши, удерживая книгу заклинаний, чтобы прочитать более подробную информацию о заклинании.
С другой стороны, свитки служат для другой цели: щелчок правой кнопкой мыши в то время как удержание одной вызывает заклинание, связанное с ним, уничтожает свиток в этом процессе. Как и книги заклинаний, свитки можно найти по всему миру, но вы также можете сделать их сами, создав пустой свиток с помощью листа бумаги и нити. Затем вы можете привязать заклинание к свитку с помощью чародейского стола обычным способом. Это приведет к тому, что количество магических кристаллов будет равно мана-стоимости заклинания (округлено до ближайшего к MANA_PER_CRYSTAL).
Однако, чтобы связать заклинание с свитком, требуется знание этого заклинания, полученное только при его использовании, поэтому если вы найдете мощную книгу заклинаний, но не имеете жезла для заклинания, вы не можете просто создать свиток и использовать. Тем не менее, если вы найдете мощное заклинание и книгу заклинаний для одного и того же заклинания, вы можете сделать столько свитков для него, сколько хотите, и произнести заклинание, даже не нуждаясь в достаточно мощной палочке.
Свитки в основном полезны, когда вам нужно использовать заклинание один или два раза в конкретном месте, но не хотите, чтобы он занимал слот в вашем жезле.
Однако следует отметить, что свитки в лучшем случае являются неэффективным методом использования заклинаний.
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_COLOUR, APPRENTICE_COLOURученикRESET_COLOUR, ADVANCED_COLOURпродвинутый RESET_COLOURи MASTER_COLOURмастерRESET_COLOUR. Каждый уровень более мощный, чем последний.
BASIC_COLOURначинающий RESET_COLOURжезлы-которые могут быть созданы. Они выдерживают BASIC_MAX_CHARGE мана, и может использовать только заклинания для начинающих. Начинающие заклинания достаточно просты, чтобы их бросали все, и они обычно не стоят много маны. Это не обязательно означает, что они бесполезны на более высоких уровнях; Их низкая стоимость делает некоторые заклинания начинающих полезными даже тогда, когда у вас есть доступ к мастер-заклинаниям..
APPRENTICE_COLOURУченик RESET_COLOURжезлы следующие после начинающих. Они выдерживают APPRENTICE_MAX_CHARGE ману и может применять заклинания для начинающих и учеников. Ученики заклинаний немного более впечатляющие, чем заклинания начинающих, но обычно стоят дороже.
ADVANCED_COLOURПродвинутый RESET_COLOURжезлы довольно редки и гораздо мощнее. Они могут использовать все заклинания, кроме мастер-заклинаний, и удерживать ADVANCED_MAX_CHARGE ману. Расширенные заклинания могут предоставлять сверхчеловеческие силы, такие как невидимость и наносить урон врагам.
MASTER_COLOURМастер RESET_COLOURжезлы самые могучие в мире. Они выдерживают MASTER_MAX_CHARGE ману, И может накладывать любое заклинание. Магистры заклинаний очень редки, и заклинания могут нанести полный урон не только врагам, но даже самому миру. Используйте с осторожностью.
PAGEBREAK
SECTION Стихии
Стихии
------------------------------
Заклинания принадлежат к различным элементам, которые описывают природу заклинания и также имеют перки при использовании с определенными жезлами.
FIRE_COLOURОгонь
Пожалуй, самый разрушительный элемент, огонь касается горения, лавы и взрывов. Мощный пиромант развяжет ад своим врагам и, возможно, запустит мир в этом процессе. Большинство заклинаний с огненной атакой поджигает цель, нанося ей постоянный урон с течением времени. Однако будьте осторожны, что заклинания огня могут не влиять на нижних мобов.
ICE_COLOURЛёд
Элемент льда сделан из всего, что холодно. Морозные заклинания часто замедляют врагов или замораживают их полностью, и особенно эффективны против существ огня. Магия магии льда может оказаться столь же полезной и вне боя, как замораживание воды для пересечения реки.
LIGHTNING_COLOURМолния
Этот элемент касается молнии, штормов и погоды. Мощный штормовой маг - это сила, с которой нужно считаться, а некоторые обладают способностью призывать молнию по желанию. Молниеносные заклинания часто наносят урон множеству врагов сразу и обычно ищут свою цель, делая их эффективной атакой против любых мобов ... но остерегайтесь криперов.
NECROMANCY_COLOURНекромантия
Некромантия - это элемент тьмы, хаоса и нежити. Некроманты таинственны и часто рассматриваются как злые, хотя обычно это не так. Заклинания некромантии обычно используются, чтобы призвать существ, чтобы сражаться за вас или даже сгибать волю ваших врагов.
EARTH_COLOURЗемля
Элемент земли сфокусирован на природном мире: животных, растениях, ветре и т. п. Магия Земли разнообразна и принимает самые различные формы: от отравления врагов до развязывания ярости погоды. Земные заклинания представляют собой смесь атак, защиты и полезности.
SORCERY_COLOURКолдовство
Волшебство - это элемент силы и изменения. Волшебники манипулируют светом, гравитацией и даже самой реальностью, чтобы соответствовать их потребностям. Колдовские заклинания могут использоваться, помимо всего прочего, для предоставления магическим силам заклинателя или перемещения предметов по их желанию.
HEALING_COLOURИсцеление
Элемент исцеления связан с защитой и регенерацией. Целители стараются как можно больше защитить себя и своих союзников и как таковые могут быть очень трудными противниками. Хотя обычно не используется в качестве атаки, очищающий свет некоторых исцеляющих заклинаний нанесет значительный урон нежити. Исцеляющие заклинания незаменимы в бою.
Границы между различными элементами не всегда различны, и некоторые заклинания несут в себе черты других элементов, отличных от их собственных.
Если вам повезет, вы можете напасть на элементарный жезл. Эти жезлы позволят вам использовать заклинания правильного элемента для большей силы, чем обычно.
PAGEBREAK
SECTION Одеяние Волшебника
Одеяние Волшебника
------------------------------
Как волшебник, вам понадобится что-то, чтобы защитить вас от существ, с которыми вы сражаетесь. Однако обычные доспехи не сделают этого. Чтобы максимально использовать ваши заклинания, вам понадобятся магические доспехи: шляпа, халаты, лосины и сапоги. В отличие от обычной брони, они не сломаются. Вместо этого они используют тайную энергию для защиты носителя. Это, конечно, означает, что они должны быть заряжены магическими кристаллами, как и жезлы. К счастью, эти предметы одежды не потребляют много маны. Зарядите их, как жезл в чародейском столе или в колбе маны, но будьте осторожны - если у них закончится мана, вы окажетесь беззащитными.
Вы можете получить волшебную броню, создавая ее из магического шелка, получаемого при создании нитки с магическим кристаллом.
Те волшебники, которые посвящают себя практике одного элемента, иногда носят специальные одежды, которые дают бонусы за этот элемент. Полные комплекты такой одежды очень популярны среди мастеров, и их не так просто найти.
Легенда говорит о тайной печати, используемой самыми могущественными волшебниками, чтобы значительно улучшить их броню.
PAGEBREAK
SECTION Волшебники И Башни
Волшебники И Башни
------------------------------
Не бойтесь - вы не единственный практикующий в этом мире. В ваших путешествиях вы можете встретить высокие башни с характерными остроконечными крышами. Это резиденции волшебников. Жизнь одиночества может иногда приводить в замешательство магов, но они, как правило, дружелюбные люди, которые готовы поделиться с вами своими знаниями, хотя и за определенную плату. Ожидайте оплатить драгоценные металлы и драгоценные камни, и взамен вы получите много чудесных загадок. Если, однако, это магическое заклинание, которое вы ищете, вам нужно поговорить со специалистом.
PAGEBREAK
PAGEBREAK
SECTION Рецепты
Рецепты
------------------------------
PAGEBREAK
PAGEBREAK
Рецепты
------------------------------
PAGEBREAK
PAGEBREAK
Рецепты
------------------------------
PAGEBREAK
PAGEBREAK
Рецепты
------------------------------
PAGEBREAK
PAGEBREAK
Credits
------------------------------
Electroblob's Wizardry
Version VERSION
For Minecraft MCVERSION
Designed, coded and textured by Electroblob
Thanks to Minecraft Forge and MCP, without which this mod would not have been possible.
Thanks also to the Minecraft modding community, which always has an answer to my modding problems!
In addition, I'd like to thank the following individuals for their contributions to the mod:
Code:
- Corail31
- 12foo
- Shadows-of-Fire
- HellFirePvP
Translations:
- Russian: VilagVil
- Spanish and Mexican Spanish: MadWrist
- Chinese: ZHENGLOC and dragon-evol
Lightning ray sound effect from OhhWowProductions
@@ -295,8 +295,10 @@
"title": "导言",
"text": [
"向你致以敬意,巫师! 这本书介绍了数种魔法类别以及操纵这些元素的方法。我必须提醒你,这本书并不只是像现在这样,看起来十分普通 —— 当你在探索这个世界时,书中新的内容会不断地具现出来。",
" 向你致以敬意,巫师!",
"这本书介绍了数种魔法类别以及操纵这些元素的方法。我必须提醒你,这本书并不只是像现在这样看起来十分普通——当你在探索这个世界时,书中新的内容会不断地具现出来。",
"点击单箭头按钮可以切换页数,点击双箭头按钮可以在章节之间切换,点击中心按钮可以返回目录。",
"点击紫色的链接将会直接跳转到相关页面,右键书签将会把书签移动到当前页面,左键书签将会返回标记页面。"
@@ -318,17 +320,17 @@
"include_in_contents": "main_contents",
"text": [
"想要开始你的巫术之旅你需要:",
"想要开始你的巫术之旅你需要:",
"- 一把魔杖,合成如下所示:",
"-一把魔杖,合成如下所示:",
"#recipe magic_wand",
"- 一个@arcane_workbench 奥术工作台@,合成如下所示:",
"-一个@arcane_workbench 奥术工作台@,合成如下所示:",
"#recipe arcane_workbench",
"- 一本@spells 法术@书。你可以在战利品箱中找到法术书,它也会以掉落物形式出现,你也可以与其他巫师交易。当然你也可以制作一本初始的法术书:魔法飞弹,如下所示:",
"-一本@spells 法术@书。你可以在战利品箱中找到法术书,它也会以掉落物形式出现,你也可以与其他巫师交易。当然你也可以制作一本初始的法术书:魔法飞弹,如下所示:",
"#recipe magic_missile_spell_book",
@@ -410,7 +412,7 @@
],
"text": [
"奥术工作台外观上与附魔台很相似,它可以用来为你的魔杖充能、升级 ,以及绑定@spells 法术@到你的@wands 魔杖@。制作方法如下所示:",
"奥术工作台外观上与附魔台很相似,它可以用来为你的魔杖充能、升级,以及绑定@spells 法术@到你的@wands 魔杖@。制作方法如下所示:",
"#recipe arcane_workbench",
@@ -480,7 +482,7 @@
],
"text": [
"作为一名巫师,你需要一些东西在战斗时保护你不受过高的伤害,普通的盔甲可无法承此重任。为了能够在提供保护时还能让你最高效率地使用的魔力,你需要一套巫师护具:包括帽子、长袍、裤子和靴子。与普通盔甲不同的是,它们耐久归零之后不会消失。而且,蕴藏在其中的奥术能量将会保护穿戴者。当然,这意味着它们必须使用水晶充能,这一点和魔杖很相似。幸运的是,这些护具不太消耗@mana 魔力@。你可以像和魔杖那样,将其放置在@arcane_workbench 奥术工作台@,或者使用@mana_flasks 魔力瓶@为其充能,但是要小心-如果护具耗尽了魔力,它们将不再提供任何保护效果。",
"作为一名巫师,你需要一些东西在战斗时保护你不受过高的伤害,普通的盔甲可无法承此重任。为了能够在提供保护时还能让你最高效率地使用的魔力,你需要一套巫师护具:包括帽子、长袍、裤子和靴子。与普通盔甲不同的是,它们耐久归零之后不会消失。而且,蕴藏在其中的奥术能量将会保护穿戴者。当然,这意味着它们必须使用水晶充能,这一点和魔杖很相似。幸运的是,这些护具不太消耗@mana 魔力@。你可以像和魔杖那样,将其放置在@arcane_workbench 奥术工作台@,或者使用@mana_flasks 魔力瓶@为其充能,但是要小心如果护具耗尽了魔力,它们将不再提供任何保护效果。",
"#image wizard_armour",
@@ -527,7 +529,7 @@
],
"text": [
"在你的旅行中,你可能在野外会不时地遇到一种奇怪的,发光的花。这些独特的花朵被称为水晶花,它们能够高效的聚集@mana 魔力@ - 直到今天,还没有人能确定它能够高效聚集魔力的原因。但是我们知道,它们可以被收集和制作成魔力水晶,使得它们成为相当有用的地上的魔力来源。然而,因为花的尺寸很小,而且它们无法密集生长,所以通过这种方式收获的魔力并不是很多",
"在你的旅行中,你可能在野外会不时地遇到一种奇怪的,发光的花。这些独特的花朵被称为水晶花,它们能够高效的聚集@mana 魔力@ - 直到今天,还没有人能确定它能够高效聚集魔力的原因。但是我们知道,它们可以被收集和制作成魔力水晶,使得它们成为相当有用的地上的魔力来源。然而,因为花的尺寸很小,而且它们无法密集生长,所以通过这种方式收获的魔力并不是很多",
"#image crystal_flower",
"#recipe crystal_flower_to_crystals"
@@ -654,7 +656,7 @@
],
"text":[
"@wands 魔杖@和@spells 法术@分成四阶:#colour_novice新手#colour_reset#colour_apprentice学徒#colour_reset#colour_advanced进阶 #colour_reset#colour_master大师#colour_reset。每一阶都比上一阶更强大。",
"@wands 魔杖@和@spells 法术@分成四阶:#colour_novice新手#colour_reset#colour_apprentice学徒#colour_reset#colour_advanced进阶#colour_reset#colour_master大师#colour_reset。每一阶都比上一阶更强大。",
"#image tiers",
@@ -684,19 +686,19 @@
"#image elements",
"#colour_fire火焰#colour_reset \n 它或许是最具破坏性的元素,火与燃烧、熔岩和爆炸有关。一位强大的火术师能够释放出地狱烈焰灼烧他的敌人,并可能在这个过程中点燃整个世界。大多数攻击型火焰法术都会点燃目标,造成持续的伤害。然而,要注意火系法术可能对下界生物没有效果。",
"#colour_fire火焰#colour_reset 它或许是最具破坏性的元素,火与燃烧、熔岩和爆炸有关。一位强大的火术师能够释放出地狱烈焰灼烧他的敌人,并可能在这个过程中点燃整个世界。大多数攻击型火焰法术都会点燃目标,造成持续的伤害。然而,要注意火系法术可能对下界生物没有效果。",
"#colour_ice冰霜#colour_reset \n 冰元素囊括了所有与寒冷有关的事物,冰霜法术通常会让敌人减速或者完全冻结,同时对火焰生物能造成额外伤害。冰霜魔法在战斗之外也同样有用,比如冻住河流,让你方便的过河。",
"#colour_ice冰霜#colour_reset 冰元素囊括了所有与寒冷有关的事物,冰霜法术通常会让敌人减速或者完全冻结,同时对火焰生物能造成额外伤害。冰霜魔法在战斗之外也同样有用,比如冻住河流,让你方便的过河。",
"#colour_lightning雷电#colour_reset \n 这种元素与闪电,风暴和天气有关。绝不可忽视的一位强大的雷术师的力量,他们能够使雷电屈从于他们的意志。雷电法术通常能够一次性伤害多个敌人,并且能够自动寻找目标,这使得它们能有效地攻击任何生物…… 但是要小心爬行者。",
"#colour_lightning雷电#colour_reset 这种元素与闪电,风暴和天气有关。绝不可忽视的一位强大的雷术师的力量,他们能够使雷电屈从于他们的意志。雷电法术通常能够一次性伤害多个敌人,并且能够自动寻找目标,这使得它们能有效地攻击任何生物…… 但是要小心爬行者。",
"#colour_necromancy死灵#colour_reset \n 死灵元素与黑暗,混乱与亡灵相关。操纵死灵元素的巫师十分神秘,而且通常被常人认为是邪恶的,但实际上往往并不是这样。死灵法术通常能够召唤@creatures 魔法生物@为你而战,亦可以扭曲敌人的意志。",
"#colour_necromancy死灵#colour_reset 死灵元素与黑暗,混乱与亡灵相关。操纵死灵元素的巫师十分神秘,而且通常被常人认为是邪恶的,但实际上往往并不是这样。死灵法术通常能够召唤@creatures 魔法生物@为你而战,亦可以扭曲敌人的意志。",
"#colour_earth自然#colour_reset \n 自然元素与自然相关:动物,植物,风,以及与这些相似的。自然魔法种类繁多,形式多样,既可以毒害敌人,亦可展现天气狂暴的一面。自然法术集合了攻击、防御和功能类法术。",
"#colour_earth自然#colour_reset 自然元素与自然相关:动物,植物,风,以及与这些相似的。自然魔法种类繁多,形式多样,既可以毒害敌人,亦可展现天气狂暴的一面。自然法术集合了攻击、防御和功能类法术。",
"#colour_sorcery秘法#colour_reset \n 秘法元素与力场与变化有关。秘术师可以操纵光、重力甚至是现实本身来满足他们的需要。此外,秘法系法术可以赋予施法者奇特的魔法能力,或者可以帮助施法者移动他所希望移动的目标。",
"#colour_sorcery秘法#colour_reset 秘法元素与力场与变化有关。秘术师可以操纵光、重力甚至是现实本身来满足他们的需要。此外,秘法系法术可以赋予施法者奇特的魔法能力,或者可以帮助施法者移动他所希望移动的目标。",
"#colour_healing治愈#colour_reset \n 治愈元素侧重于防御和再生,治疗师尽可能多地保护他们自己和他们的盟友,因此在特殊情况下会非常难对付。虽然一般不用于攻击,但某些治疗法术的净化之光会对亡灵造成相当大的伤害。治疗法术在战斗中是必不可少的。",
"#colour_healing治愈#colour_reset 治愈元素侧重于防御和再生,治疗师尽可能多地保护他们自己和他们的盟友,因此在特殊情况下会非常难对付。虽然一般不用于攻击,但某些治疗法术的净化之光会对亡灵造成相当大的伤害。治疗法术在战斗中是必不可少的。",
"不同元素之间的界限并不总是泾渭分明的,有些法术反而具有其它元素的特征。",
@@ -320,19 +320,19 @@
"要開始使用法術,你需要準備:",
"法杖, 請依圖示合成:",
"法杖,請依圖示合成:",
"#recipe magic_wand",
"\n\n》@arcane_workbench 法術工作台@ 合成方式如圖:",
"@arcane_workbench 法術工作台@,合成方式如圖:",
"#recipe arcane_workbench",
"@spells 法術書@\n這個可以在箱子裡找到,或從怪物身上掉落,或向法師購買。\n\n\n\n不然你也可以自己合成一個\n初學者法術【魔法彈】,\n如圖所示:",
"@spells 法術書@這個可以在箱子裡找到,或從怪物身上掉落,或向法師購買。不然你也可以自己合成一個初學者法術【魔法彈】,如圖所示:",
"#recipe magic_missile_spell_book",
"你還需要準備一大堆魔法水晶\n來為法杖供應@mana 法力@。"
"你還需要準備一大堆魔法水晶來為法杖供應@mana 法力@。"
]
},
@@ -344,7 +344,7 @@
],
"text": [
"法力是賦予法師力量的魔法能量,其本身並非實體的物質,反而是可滲入於萬物之中的永恆能量。特別的是,法力蘊藏在於地下岩石中所找到的天然水晶內。\n@wands 法杖@可儲存法力,並在施法時\n將法力引導到@spells 法術@上。\n不同的法術會依其力量強度及持續時間消耗不同的法力值。",
"法力是賦予法師力量的魔法能量,其本身並非實體的物質,反而是可滲入於萬物之中的永恆能量。特別的是,法力蘊藏在於地下岩石中所找到的天然水晶內。@wands 法杖@可儲存法力,並在施法時將法力引導到@spells 法術@上。不同的法術會依其力量強度及持續時間消耗不同的法力值。",
"#image crystal_ore",
@@ -362,17 +362,17 @@
],
"text": [
"法杖是法師首選的器具。\n你能用它來施展任何法杖能力\n所及的@spells 法術@(請參閱@tiers 等級@章節)\n。\n法杖的種類很多,不過當然都得從基礎法杖開始。",
"法杖是法師首選的器具。你能用它來施展任何法杖能力所及的@spells 法術@(請參閱@tiers 等級@章節)法杖的種類很多,不過當然都得從基礎法杖開始。",
"#image magic_wand",
"大多數的法杖都誕生於一個簡單的製作方式。\n準備一顆某種類型的魔法水晶,\n將水晶裝在木棒的一端,\n再於另一端黏上一顆金粒。\n水晶自然是法杖力量的源頭,\n因為它提供了引導@spells 法術@所需的\n焦點。而其餘的部分也很重要,不只是因為提供了握住法杖的地方,更是指引@mana 法力@前進的路徑\n。",
"大多數的法杖都誕生於一個簡單的製作方式。準備一顆某種類型的魔法水晶,將水晶裝在木棒的一端,再於另一端黏上一顆金粒。水晶自然是法杖力量的源頭,因為它提供了引導@spells 法術@所需的焦點。而其餘的部分也很重要,不只是因為提供了握住法杖的地方,更是指引@mana 法力@前進的路徑。",
"隨著法杖施展了愈多法術,\n其變得愈能駕馭@spells 法術@\n因此也能施展更強大的法術。\n這樣的成長可以從法杖外觀上的細微變化中發現,隨著法杖愈來愈強,水晶會變得更加明亮,\n顏色也可能會根據其@elements 元素@而\n產生變化。過了一段時間之後,法杖本身的木材也會開始扭曲生長成各種複雜的形狀。",
"隨著法杖施展了愈多法術,其變得愈能駕馭@spells 法術@,因此也能施展更強大的法術。這樣的成長可以從法杖外觀上的細微變化中發現,隨著法杖愈來愈強,水晶會變得更加明亮,顏色也可能會根據其@elements 元素@而產生變化。過了一段時間之後,法杖本身的木材也會開始扭曲生長成各種複雜的形狀。",
"當你拿著法杖時,畫面的角落會顯示出目前法杖所選的法術及其圖示,而在施放法術之後,還會顯示冷卻條來表示直到下次施展所需等待的時間,它還會顯示法杖中的前一個和下一個法術名稱。按下《#next_spell_key 鍵》及《#previous_spell_key 鍵》可切換法術(這些都可在【選項】->【按鍵設定】中變更),你也可以在潛行時使用滑鼠滾輪來切換法術。",
"當你將游標停留在物品欄的法杖上時,會顯示法杖中儲存的\n@mana 法力@,伴隨目前所選的@spells 法術@及其\n特殊能力。\n將法杖放入@arcane_workbench 法術工作台@則可\n看見更詳細的資訊。"
"當你將游標停留在物品欄的法杖上時,會顯示法杖中儲存的@mana 法力@,伴隨目前所選的@spells 法術@及其特殊能力。將法杖放入@arcane_workbench 法術工作台@則可看見更詳細的資訊。"
]
},
@@ -384,13 +384,13 @@
],
"text": [
"沒有法術的@wands 法杖@沒有作用。\n法術的記錄形式有兩種:\n一種是永久性的書本,\n一種是暫時性的卷軸。",
"沒有法術的@wands 法杖@沒有作用。法術的記錄形式有兩種:一種是永久性的書本,一種是暫時性的卷軸。",
"法術書本身無法使用,而是用於將書中記載的法術存入@wands 法杖@。\n在世界各地都能發現法術書,應該用不了多少時間你就能找到一本。當你找到後,可將游標停留在書上,看一下這本法術書的基本資訊,也可以拿著書點擊滑鼠右鍵以閱讀更詳細的資料。",
"法術書本身無法使用,而是用於將書中記載的法術存入@wands 法杖@。在世界各地都能發現法術書,應該用不了多少時間你就能找到一本。當你找到後,可將游標停留在書上,看一下這本法術書的基本資訊,也可以拿著書點擊滑鼠右鍵以閱讀更詳細的資料。",
"相對而言卷軸則有不同的用途: 拿著卷軸點擊滑鼠右鍵便會施展上面的法術並用掉卷軸。跟法術書一樣,卷軸在世界各地都能找到,但你也可以自己@enchanting_scrolls 製作@。",
"在你準備進行某個任務時,有些法術可能只會用到一兩次,\n所以你不想讓那些法術占用\n你的@wands 法杖@空間,此時卷軸就非常\n有用。They also have the advantage of being able to instantly cast spells that would normally require a charge-up period. 不過得注意,比起法杖,卷軸還是效率較差的施法方式。",
"在你準備進行某個任務時,有些法術可能只會用到一兩次,所以你不想讓那些法術占用你的@wands 法杖@空間,此時卷軸就非常有用。They also have the advantage of being able to instantly cast spells that would normally require a charge-up period. 不過得注意,比起法杖,卷軸還是效率較差的施法方式。",
"未經訓練的眼睛無法閱讀法術中的魔法符文。然而若要鑑定一個法術,你當然可以冒著發生意外的風險來施展看看結果,但即便如此許多法術是要在特定的條件下才會發生作用。不過即便如此,還是有可能在施法時誤用了未鑑定的法術,其潛在的危險性取決於這個法術有多強大。因此更安全可靠的選擇是使用鑑定卷軸,可以在箱子裡找到或是向法師購買。拿著鑑定卷軸點擊滑鼠右鍵便會用掉卷軸並鑑定你快捷欄中第一個未知的法術書或卷軸。"
]
@@ -410,7 +410,7 @@
],
"text": [
"法術工作台看起來有點像附魔台, 用來升級你的@wands 法杖@、\n為其補充法力和存入@spells 法術@。\n\n其合成方式如下:",
"法術工作台看起來有點像附魔台,用來升級你的@wands 法杖@、為其補充法力和存入@spells 法術@。其合成方式如下:",
"#recipe arcane_workbench",
@@ -427,7 +427,7 @@
],
"text": [
"要將@spells 法術@存入你的@wands 法杖@,只要將\n法杖放入工作台中央的槽中,然後將法術書放入周圍其中一個槽並按下按鈕。此時你會注意到,在這個過程中,法術書並沒有受到任何影響,這是因為存入法術的動作,並不是將法術從法術書中取走,只是將法術抄寫至法杖中而已。因此你可以重複這個動作,盡量將想要的法術存入你的法杖。你一次最多只能存入五種法術到法杖中,不過可用協調升級來增加法術存量。"
"要將@spells 法術@存入你的@wands 法杖@,只要將法杖放入工作台中央的槽中,然後將法術書放入周圍其中一個槽並按下按鈕。此時你會注意到,在這個過程中,法術書並沒有受到任何影響,這是因為存入法術的動作,並不是將法術從法術書中取走,只是將法術抄寫至法杖中而已。因此你可以重複這個動作,盡量將想要的法術存入你的法杖。你一次最多只能存入五種法術到法杖中,不過可用協調升級來增加法術存量。"
]
},
"charging_wands": {
@@ -438,7 +438,7 @@
],
"text": [
"要幫@wands 法杖@補充法力,先將法杖\n放入法術工作台中央的槽,並在左下方那個槽放入魔法水晶,然後按下按鈕。\n每個水晶相當於#mana_per_crystal點的@mana 法力@\n而法杖只會在需要時用掉水晶,因此你可以將水晶留在工作台內,以便需要時供應。但是請記得,法杖只能取用整數單位的水晶,舉例來說,如果法杖只需要30點法力,那補充法力時會有#example_charging_loss點法力浪費掉。"
"要幫@wands 法杖@補充法力,先將法杖放入法術工作台中央的槽,並在左下方那個槽放入魔法水晶,然後按下按鈕。每個水晶相當於#mana_per_crystal點的@mana 法力@,而法杖只會在需要時用掉水晶,因此你可以將水晶留在工作台內,以便需要時供應。但是請記得,法杖只能取用整數單位的水晶,舉例來說,如果法杖只需要30點法力,那補充法力時會有#example_charging_loss點法力浪費掉。"
]
},
"upgrading_wands": {
@@ -449,7 +449,7 @@
],
"text": [
"你需要對應@tiers 等級@的法術寶典來\n升級你的@wands 法杖@或進行特殊的法\n杖升級。這兩種東西都可從怪物的掉落物或向法師購買獲得。要升級法杖,先將法杖放入法術工作台中央的槽,並在右上方的槽放入升級物後按下按鈕。",
"你需要對應@tiers 等級@的法術寶典來升級你的@wands 法杖@或進行特殊的法杖升級。這兩種東西都可從怪物的掉落物或向法師購買獲得。要升級法杖,先將法杖放入法術工作台中央的槽,並在右上方的槽放入升級物後按下按鈕。",
"特殊的法杖升級可加強法杖某方面的能力,每種升級最高只能疊加三次,而法杖的總升級數取決於法杖的等級。升級後就無法移除。"
]
@@ -462,7 +462,7 @@
],
"text": [
"法術工作台也能用來將@spells 法術@\n存入卷軸。要製作卷軸,你需要先用一張紙及一些線來合成空白卷軸,然後選一本想要作成卷軸的法術書,最後準備足夠的魔法水晶以提供施展這個法術的@mana 法力@。",
"法術工作台也能用來將@spells 法術@存入卷軸。要製作卷軸,你需要先用一張紙及一些線來合成空白卷軸,然後選一本想要作成卷軸的法術書,最後準備足夠的魔法水晶以提供施展這個法術的@mana 法力@。",
"#recipe blank_scroll",
@@ -480,7 +480,7 @@
],
"text": [
"身為一位法師,在與生物搏鬥時需要一些東西來保護自己。雖然也能使用一般的護甲,但是為了充分發揮你的法術,你還是需要一套法師服,包括帽子、長袍、褲子和鞋子。\n與一般護甲不同的是,法師服不會破損,其使用魔法能量來保護穿著的人。因此跟法杖一樣,需要魔法水晶來補充能量。不過幸好這些服裝不會消耗太多\n@mana 法力@。\n法師服補充能量的方式也跟法杖一樣,可以用@arcane_workbench 法術工作台@或\n@mana_flasks 法力瓶@來補充,但是必須當心,\n如果法師服的法力耗盡了,你會發現自己毫無防禦力。",
"身為一位法師,在與生物搏鬥時需要一些東西來保護自己。雖然也能使用一般的護甲,但是為了充分發揮你的法術,你還是需要一套法師服,包括帽子、長袍、褲子和鞋子。與一般護甲不同的是,法師服不會破損,其使用魔法能量來保護穿著的人。因此跟法杖一樣,需要魔法水晶來補充能量。不過幸好這些服裝不會消耗太多@mana 法力@。法師服補充能量的方式也跟法杖一樣,可以用@arcane_workbench 法術工作台@或@mana_flasks 法力瓶@來補充,但是必須當心,如果法師服的法力耗盡了,你會發現自己毫無防禦力。",
"#image wizard_armour",
@@ -514,7 +514,7 @@
],
"text": [
"只是待在家裡是無法成為法術大師的,到外頭探索充滿魔法的世界吧!\n若你勇於挑戰,古代遺址、遺物以及不管好的或壞的神秘生物,都等著你發現。\n最偉大的法師同時也最具好奇心,他們會不斷的探索周遭環境,並嘗試所發現的東西,來獲得豐富的知識及強大的力量。",
"只是待在家裡是無法成為法術大師的,到外頭探索充滿魔法的世界吧!若你勇於挑戰,古代遺址、遺物以及不管好的或壞的神秘生物,都等著你發現。最偉大的法師同時也最具好奇心,他們會不斷的探索周遭環境,並嘗試所發現的東西,來獲得豐富的知識及強大的力量。",
"雖然法師不免大多的時間都是孤身一人,但知識的分享也是學習魔法藝術重要的一環。找尋其他法師,盡可能從他們身上學習更多知識,溝通才是一切最大的力量。"
],
@@ -527,7 +527,7 @@
],
"text": [
"在你的旅途當中,可能在野外會不時遇到奇怪的發光花朵,這些獨特的花稱為水晶花,它們具有聚集@mana 法力@的神奇能力,至今還不\n知道原因。不過我們卻知道這些水晶花,可經由採集製作以提取法力成為水晶,這使它們成為地面上相當有用的法力來源。然而由於這種花並不大,而且生長的土地都很小塊,因此這種方式所能獲得的法力其實很有限。",
"在你的旅途當中,可能在野外會不時遇到奇怪的發光花朵,這些獨特的花稱為水晶花,它們具有聚集@mana 法力@的神奇能力,至今還不知道原因。不過我們卻知道這些水晶花,可經由採集製作以提取法力成為水晶,這使它們成為地面上相當有用的法力來源。然而由於這種花並不大,而且生長的土地都很小塊,因此這種方式所能獲得的法力其實很有限。",
"#image crystal_flower",
"#recipe crystal_flower_to_crystals"
@@ -541,13 +541,13 @@
],
"text": [
"害怕嗎?你並不是這個世界上唯一會使用魔法的人。\n在你的旅途中,你可能會遇到具有獨特尖頂或雙尖頂的高塔,這些是法師同伴居住的地方。\n隱居的生活使法師們有時候會有點古怪,但是他們通常還是友善的,而且只要你願意付出代價,還是會樂意與你分享他們的知識。\n在支付了貴重金屬及寶石後,你會收到許多驚奇的法術作為回報。",
"害怕嗎?你並不是這個世界上唯一會使用魔法的人。在你的旅途中,你可能會遇到具有獨特尖頂或雙尖頂的高塔,這些是法師同伴居住的地方。隱居的生活使法師們有時候會有點古怪,但是他們通常還是友善的,而且只要你願意付出代價,還是會樂意與你分享他們的知識。在支付了貴重金屬及寶石後,你會收到許多驚奇的法術作為回報。",
"如果你想尋找的是@tiers 大師級@法術,\n那你得跟專門的人交談。",
"如果你想尋找的是@tiers 大師級@法術,那你得跟專門的人交談。",
"#image wizard_tower",
"不幸的是,有少數法師並不歡迎訪客。這些法師通常已被驅逐,所以對於任何闖入地盤的人都充滿敵意。\n接近這些傢伙要特別小心,並做好抵擋強大魔法的準備。只要擊敗他們,他們的知識就會成為你的了。",
"不幸的是,有少數法師並不歡迎訪客。這些法師通常已被驅逐,所以對於任何闖入地盤的人都充滿敵意。接近這些傢伙要特別小心,並做好抵擋強大魔法的準備。只要擊敗他們,他們的知識就會成為你的了。",
"有一點必須知道,沒有法師會接受對他們攻擊或盜取他們東西的人,他們肯定不會善罷甘休。"
]
@@ -562,11 +562,11 @@
"古老魔法的遺跡散落在世界各處,其中最著名的是刻有許多符號及符文的石頭結構。這些廢墟看起來像是某種古代文明的遺跡,無論建造它們的是誰或是什麼,顯然具有相當豐富的魔法知識,且用來在這些地方設置持續至今的防衛魔法。",
"這些結構大致上分成兩種類型,第一種是較常見的方尖碑:\n以雕刻符文石堆成高高尖頂的結構,底部開著一塊空間,存放著過去所遺留的次等魔法物品。",
"這些結構大致上分成兩種類型,第一種是較常見的方尖碑:以雕刻符文石堆成高高尖頂的結構,底部開著一塊空間,存放著過去所遺留的次等魔法物品。",
"#image obelisk",
"這些結構通常受到魔法保護,一旦有人靠近就會召喚出充滿敵意的@creatures 魔法生物@來攻擊人類。\n對抗這些生物並摧毀其魔法源頭,那些遺物就是你的了。"
"這些結構通常受到魔法保護,一旦有人靠近就會召喚出充滿敵意的@creatures 魔法生物@來攻擊人類。對抗這些生物並摧毀其魔法源頭,那些遺物就是你的了。"
]
},
"shrines": {
@@ -577,11 +577,11 @@
],
"text": [
"第二種較為罕見的結構稱之為神殿,由一個中央基座及圍繞在四周的符文石柱所組成。基座上方擺著一個裝有古代@artefacts 神器@的\n寶箱,並通常施加了防護魔法鎖,以防他人竊取。整個結構還受到封鎖力場保護,使擅闖者無法逃離。",
"第二種較為罕見的結構稱之為神殿,由一個中央基座及圍繞在四周的符文石柱所組成。基座上方擺著一個裝有古代@artefacts 神器@的寶箱,並通常施加了防護魔法鎖,以防他人竊取。整個結構還受到封鎖力場保護,使擅闖者無法逃離。",
"#image shrine",
"由於這些神殿的重要意義及巨大的神秘力量,更別說裡面的寶物,對於志氣高昂的法師特別有吸引力。\n\n但是務必謹慎,有許多關於法師被關在封鎖區內,可能因為幽閉恐懼症導致慢慢發瘋的報導。且愈來愈多人認為,這就是神殿防護魔法的一個部分,而被關在其中的法師,其實是被控制用來守護神殿。這對於膽敢前往冒險的人來說,無疑是令人不寒而慄的結局..."
"由於這些神殿的重要意義及巨大的神秘力量,更別說裡面的寶物,對於志氣高昂的法師特別有吸引力。但是務必謹慎,有許多關於法師被關在封鎖區內,可能因為幽閉恐懼症導致慢慢發瘋的報導。且愈來愈多人認為,這就是神殿防護魔法的一個部分,而被關在其中的法師,其實是被控制用來守護神殿。這對於膽敢前往冒險的人來說,無疑是令人不寒而慄的結局..."
]
},
"library_ruins": {
@@ -620,7 +620,7 @@
],
"text": [
"除了法師,還有許多其它生物也會使用魔法。其中有許多是源自於魔法,且大部分都能用特定的@spells 法術@召喚。會看到這些生物,\n大多是在守護@obelisks 方尖碑@,但也可能\n遇到了強大的召喚法師。只有非常少數的神秘生物才會偶爾在野外發現。",
"除了法師,還有許多其它生物也會使用魔法。其中有許多是源自於魔法,且大部分都能用特定的@spells 法術@召喚。會看到這些生物,大多是在守護@obelisks 方尖碑@,但也可能遇到了強大的召喚法師。只有非常少數的神秘生物才會偶爾在野外發現。",
"A notable example is the remnant, a spirit-like being that forms naturally from the traces left behind by powerful magic and typically takes on one of the seven arcane @elements@. On their own, they are little more than a nuisance, but a swarm can quickly overwhelm the unprepared adventurer, and their innate resistance to magic makes it advisable to carry a bow or other ranged weapon.",
@@ -642,7 +642,7 @@
],
"text": [
"在探索@shrines 神殿@時,你可能會好運的\n發現某種古代魔法神器,一種能夠賦予配戴者獨特而強大能力的物品。\n目前所知的類型有三種:\n為法術附加額外能力及效果的戒指,增強防禦力的項鍊,以及各種應用魔法的寶器。\n這些神器只是放入背包是沒有用的,要擺在身上的正確位置才會發生作用。"
"在探索@shrines 神殿@時,你可能會好運的發現某種古代魔法神器,一種能夠賦予配戴者獨特而強大能力的物品。目前所知的類型有三種:為法術附加額外能力及效果的戒指,增強防禦力的項鍊,以及各種應用魔法的寶器。這些神器只是放入背包是沒有用的,要擺在身上的正確位置才會發生作用。"
]
}
}
@@ -670,7 +670,7 @@
"要提升至更高等級,首先法杖必須變得夠強大到足以引導該等級的法術。法杖會隨著施展法術而獲得成長,法術類型、法術力量、元素效果以及其它外部因素都可能會影響法杖的成長速度。",
"當法杖足夠強大,法術寶典為最終將法杖提升至下個等級的關鍵物品(請參閱@upgrading_wands 升級法杖@)\n一旦完成升級,法杖將再次朝下個等級開始成長。"
"當法杖足夠強大,法術寶典為最終將法杖提升至下個等級的關鍵物品(請參閱@upgrading_wands 升級法杖@),一旦完成升級,法杖將再次朝下個等級開始成長。"
]
},
@@ -682,23 +682,23 @@
],
"text": [
"@spells 法術@各屬於不同的元素,代表\n法術的本質,且搭配使用對應的@wands 法杖@還會加強效果。",
"@spells 法術@各屬於不同的元素,代表法術的本質,且搭配使用對應的@wands 法杖@還會加強效果。",
"#image elements",
"#colour_fire火#colour_reset \n火元素涉及燃燒、岩漿以及爆炸,大概是最具破壞性的元素。一個強大的烈焰法師可使敵人面臨煉獄般的火海,並可能在過程中毀掉這個世界。\n大部分的火系法術會讓目標著火,使他們持續受到傷害,但是對地獄的生物則沒什麼效果。",
"#colour_fire火#colour_reset 火元素涉及燃燒、岩漿以及爆炸,大概是最具破壞性的元素。一個強大的烈焰法師可使敵人面臨煉獄般的火海,並可能在過程中毀掉這個世界。大部分的火系法術會讓目標著火,使他們持續受到傷害,但是對地獄的生物則沒什麼效果。",
"#colour_ice冰#colour_reset \n冰元素來自於所有冰冷的物質。冰系法術通常會讓敵人減速,甚至使他們完全凍結,對於火系生物特別有效。\n冰凍魔法在戰鬥之外也很有用,例如使水面結冰以過河。",
"#colour_ice冰#colour_reset 冰元素來自於所有冰冷的物質。冰系法術通常會讓敵人減速,甚至使他們完全凍結,對於火系生物特別有效。冰凍魔法在戰鬥之外也很有用,例如使水面結冰以過河。",
"\n#colour_lightning電#colour_reset \n這個元素涉及雷電、風暴以及天氣。決不可小看一個強大雷電法師的力量,有些甚至能隨意召喚閃電。\n雷電法術經常能一次傷害多個敵人,還會自動搜尋目標,對任何生物都能造成有效的攻擊...但是得當心苦力怕。",
"#colour_lightning電#colour_reset 這個元素涉及雷電、風暴以及天氣。決不可小看一個強大雷電法師的力量,有些甚至能隨意召喚閃電。雷電法術經常能一次傷害多個敵人,還會自動搜尋目標,對任何生物都能造成有效的攻擊...但是得當心苦力怕。",
"#colour_necromancy死靈#colour_reset \n死靈是黑暗、渾沌以及不死生物的元素。神秘的死靈法師往往被視為邪惡,儘管通常不是這樣的。\n死靈法術常召喚@creatures 生物@來為他\n戰鬥,或進而扭曲敵人的意志。",
"#colour_necromancy死靈#colour_reset 死靈是黑暗、渾沌以及不死生物的元素。神秘的死靈法師往往被視為邪惡,儘管通常不是這樣的。死靈法術常召喚@creatures 生物@來為他戰鬥,或進而扭曲敵人的意志。",
"#colour_earth大地#colour_reset \n大地元素來自於動植物、風等自然界的的力量。大地魔法千變萬化,從毒害敵人到控制天氣,有各式各樣的形式。\n大地法術是綜合攻擊、防禦以及實用的法術。",
"#colour_earth大地#colour_reset 大地元素來自於動植物、風等自然界的的力量。大地魔法千變萬化,從毒害敵人到控制天氣,有各式各樣的形式。大地法術是綜合攻擊、防禦以及實用的法術。",
"#colour_sorcery秘術#colour_reset \n秘術是力量與變化的元素。\n秘術法師能操縱光線、重力,甚至現實世界本身來符合他們的需求。\n且不提其它用途,秘術法術可用來提供施法者魔法力量,或是任意移動物體。",
"#colour_sorcery秘術#colour_reset 秘術是力量與變化的元素。秘術法師能操縱光線、重力,甚至現實世界本身來符合他們的需求。且不提其它用途,秘術法術可用來提供施法者魔法力量,或是任意移動物體。",
"#colour_healing治療#colour_reset \n治療元素包括防禦和再生。\n治療法師會盡可能的保護自己及他們的同伴,因此可能會是非常難以對付的對手。\n治療法術在戰鬥中是不可或缺的,即便其通常不會用來進行攻擊,但是一些治療法術的淨化光芒會對不死生物造成相當大的傷害。",
"#colour_healing治療#colour_reset 治療元素包括防禦和再生。治療法師會盡可能的保護自己及他們的同伴,因此可能會是非常難以對付的對手。治療法術在戰鬥中是不可或缺的,即便其通常不會用來進行攻擊,但是一些治療法術的淨化光芒會對不死生物造成相當大的傷害。",
"不同元素之間的分界並不總是那麼明確,有些法術除了所屬元素的性質外,也會具有其它元素的特性。",
@@ -729,11 +729,11 @@
"亞肯多魔法用品公司 - 為您所需的魔法物品!",
"需要在旅行中為你的@wands 法杖@補充\n法力嗎?\n沒問題! 現在@mana 法力@可以裝瓶。\n只要用一個玻璃瓶及八個魔法水晶合成出法力瓶,就可以隨身攜帶。要用的時候,只要將你的法杖與法力瓶合成,就能將法力存入法杖。(註)",
"需要在旅行中為你的@wands 法杖@補充法力嗎?沒問題!現在@mana 法力@可以裝瓶。只要用一個玻璃瓶及八個魔法水晶合成出法力瓶,就可以隨身攜帶。要用的時候,只要將你的法杖與法力瓶合成,就能將法力存入法杖。(註)",
"#recipe medium_mana_flask",
"好消息! 即日起推出全新的小瓶裝及大瓶裝法力,可依您的需求選擇!",
"好消息!即日起推出全新的小瓶裝及大瓶裝法力,可依您的需求選擇!",
"#recipe small_mana_flask",
"#recipe large_mana_flask",
@@ -749,7 +749,7 @@
],
"text": [
"各種@spells 法術@的實體物,像是\n火焰彈、毒液彈、煙霧彈,還有電擊彈都能直接合成:",
"各種@spells 法術@的實體物,像是火焰彈、毒液彈、煙霧彈,還有電擊彈都能直接合成:",
"#recipe firebomb",
"#recipe poison_bomb",
@@ -765,7 +765,7 @@
],
"text": [
"近期的實驗顯示,在某種程度上只需要簡單的發射器就能自動施展@spells 法術@。沒有人知道原因,\n但看起來似乎是紅石的神奇特性竟然能觸發法術卷軸。只要將一些卷軸放入發射器,然後提供能量,就完成了這個機關..."
"近期的實驗顯示,在某種程度上只需要簡單的發射器就能自動施展@spells 法術@。沒有人知道原因,但看起來似乎是紅石的神奇特性竟然能觸發法術卷軸。只要將一些卷軸放入發射器,然後提供能量,就完成了這個機關..."
]
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Some files were not shown because too many files have changed in this diff Show More