Compare commits
73 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f9cf1b39db | |||
| 3fb3c1c039 | |||
| e8bc6ca725 | |||
| df531d3724 | |||
| 2728012f33 | |||
| 853df2eb42 | |||
| 0cb2165ddf | |||
| ca7e9034ed | |||
| 1322c920f5 | |||
| e5c00e3882 | |||
| c030629bab | |||
| 165d079251 | |||
| 7cc9200adf | |||
| 01a9d8c075 | |||
| 0a0a08d220 | |||
| 410768e6f3 | |||
| bbbe024bb3 | |||
| 93112d5192 | |||
| 112a562b2d | |||
| 85ca4fd100 | |||
| 136b1cc924 | |||
| e4b7d528f5 | |||
| 2903ebfbac | |||
| 931ca1b2c0 | |||
| 85e724d88a | |||
| e41f83a2dd | |||
| 69b52cfe88 | |||
| 7591821e57 | |||
| 0ce0dcf2e9 | |||
| 73811c3a6b | |||
| 2a887b7794 | |||
| ad9f482e76 | |||
| 6eaef94459 | |||
| 4f5c616240 | |||
| f5947dded9 | |||
| 77e0acc16b | |||
| e48646c5ff | |||
| 5e48fe51ea | |||
| 6b30dbef65 | |||
| d6508a2be4 | |||
| dfcadfb3bd | |||
| 7888b92129 | |||
| 5b48dffa77 | |||
| 5bf4650da1 | |||
| 8e9c270b77 | |||
| 00080331df | |||
| 27e40e2069 | |||
| 3a93877de3 | |||
| 7f70784cd3 | |||
| ed6e3df66e | |||
| eb5becbbd4 | |||
| 9599316fbc | |||
| cc1c951ef8 | |||
| d23c4cba18 | |||
| 3d30b0b96f | |||
| ad1e5d555a | |||
| 14ea5f1c72 | |||
| 709d44e4d9 | |||
| 8df00e9c41 | |||
| 8dbb0ec058 | |||
| b8310eedae | |||
| c04754afe1 | |||
| 3155aa6815 | |||
| ea27b1a081 | |||
| 4d078f9597 | |||
| 67459cbbbd | |||
| 932de4e969 | |||
| 41e28291ad | |||
| 6ae6324368 | |||
| 4858716f05 | |||
| 24fb4cfe4a | |||
| 186138d0c0 | |||
| 6690564017 |
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"homepage": "https://www.curseforge.com/minecraft/mc-mods/electroblobs-wizardry",
|
"homepage": "https://www.curseforge.com/minecraft/mc-mods/electroblobs-wizardry",
|
||||||
"promos": {
|
"promos": {
|
||||||
"1.12.2-latest": "4.3.5",
|
"1.12.2-latest": "4.3.13",
|
||||||
"1.12.2-recommended": "4.3.5"
|
"1.12.2-recommended": "4.3.13"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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. 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.5 [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.]
|
|
||||||
@@ -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
|
||||||
@@ -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 --->
|
||||||
@@ -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]
|
|
||||||
@@ -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: [change as necessary]
|
|
||||||
|
|
||||||
Question details: [explain your question here]
|
|
||||||
|
|
||||||
Other mods involved: [if this question involves other mods, list them here]
|
|
||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
# Credits
|
# Credits
|
||||||
|
|
||||||
Electroblob's Wizardry
|
Electroblob's Wizardry
|
||||||
Version 4.3.5
|
Version 4.3.7
|
||||||
For Minecraft 1.12.2
|
For Minecraft 1.12.2
|
||||||
|
|
||||||
Designed, coded and textured by Electroblob
|
Designed, coded and textured by Electroblob
|
||||||
|
|||||||
+111
-49
@@ -1,64 +1,127 @@
|
|||||||
|
import groovy.json.JsonOutput
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
jcenter()
|
gradlePluginPortal()
|
||||||
maven { url = "http://files.minecraftforge.net/maven" }
|
maven {
|
||||||
|
name 'MinecraftForge'
|
||||||
|
url 'https://maven.minecraftforge.net/'
|
||||||
|
}
|
||||||
|
maven {
|
||||||
|
name 'Garden of Fancy'
|
||||||
|
url 'https://maven.gofancy.wtf/releases'
|
||||||
|
}
|
||||||
|
//fallback for fancygradle maven
|
||||||
|
//mavenLocal()
|
||||||
|
maven {
|
||||||
|
name 'Sponge'
|
||||||
|
url 'https://repo.spongepowered.org/repository/maven-public/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT'
|
classpath 'net.minecraftforge.gradle:ForgeGradle:5.+'
|
||||||
|
classpath 'org.ajoberstar.grgit:grgit-gradle:3.1.1'
|
||||||
|
classpath group: 'wtf.gofancy.fancygradle', name: 'wtf.gofancy.fancygradle.gradle.plugin', version: '1.1.+'
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories.each {
|
||||||
|
if (it instanceof MavenArtifactRepository && it.url.toString() == "https://files.minecraftforge.net/maven") {
|
||||||
|
it.url = "https://maven.minecraftforge.net"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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.
|
apply plugin: 'net.minecraftforge.gradle'
|
||||||
|
apply plugin: 'idea'
|
||||||
|
apply plugin: 'maven-publish'
|
||||||
|
apply plugin: org.ajoberstar.grgit.gradle.GrgitPlugin
|
||||||
|
apply plugin: 'wtf.gofancy.fancygradle'
|
||||||
|
|
||||||
|
|
||||||
version = "4.3.5" // There, it matches semver, happy now?
|
version = "4.3.13"
|
||||||
group= "electroblob.wizardry"// http://maven.apache.org/guides/mini/guide-naming-conventions.html
|
group= "electroblob.wizardry"// http://maven.apache.org/guides/mini/guide-naming-conventions.html
|
||||||
archivesBaseName = "ElectroblobsWizardry"
|
archivesBaseName = "ElectroblobsWizardry"
|
||||||
|
|
||||||
sourceCompatibility = targetCompatibility = "1.8" // Need this here so eclipse task generates correctly.
|
sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' // Need this here so eclipse task generates correctly.
|
||||||
compileJava {
|
|
||||||
sourceCompatibility = targetCompatibility = "1.8"
|
|
||||||
|
minecraft {
|
||||||
|
// The mappings can be changed at any time, and must be in the following format.
|
||||||
|
// snapshot_YYYYMMDD Snapshot are built nightly.
|
||||||
|
// stable_# Stables are built at the discretion of the MCP team.
|
||||||
|
// Use non-default mappings at your own risk. they may not always work.
|
||||||
|
// Simply re-run your setup task after changing the mappings to update your workspace.
|
||||||
|
//mappings channel: 'snapshot', version: '20171003-1.12'
|
||||||
|
mappings channel: "stable", version: "39-1.12"
|
||||||
|
// makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
|
||||||
|
|
||||||
|
// accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
|
||||||
|
|
||||||
|
// Default run configurations.
|
||||||
|
// These can be tweaked, removed, or duplicated as needed.
|
||||||
|
runs {
|
||||||
|
client {
|
||||||
|
workingDirectory project.file('run')
|
||||||
|
|
||||||
|
// Recommended logging data for a userdev environment
|
||||||
|
property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP'
|
||||||
|
|
||||||
|
// Recommended logging level for the console
|
||||||
|
property 'forge.logging.console.level', 'info'
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
|
||||||
|
// Recommended logging data for a userdev environment
|
||||||
|
property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP'
|
||||||
|
|
||||||
|
// Recommended logging level for the console
|
||||||
|
property 'forge.logging.console.level', 'info'
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
maven {
|
maven {
|
||||||
// location of the maven that hosts JEI files
|
url = uri('https://www.cursemaven.com')
|
||||||
name = "Progwml6 maven"
|
content {
|
||||||
url = "http://dvs1.progwml6.com/files/maven"
|
includeGroup 'curse.maven'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
maven {
|
maven {
|
||||||
// location of a maven mirror for JEI files, as a fallback
|
name = 'Modrinth'
|
||||||
name = "ModMaven"
|
url = uri('https://api.modrinth.com/maven')
|
||||||
url = "modmaven.k-4u.nl"
|
content {
|
||||||
|
includeGroup 'maven.modrinth'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
maven {
|
maven {
|
||||||
name = "Curseforge Maven"
|
name = 'Sponge'
|
||||||
url = "https://minecraft.curseforge.com/api/maven/"
|
url = uri('https://repo.spongepowered.org/maven')
|
||||||
|
}
|
||||||
|
maven {
|
||||||
|
url = uri('https://maven.blamejared.com')
|
||||||
|
}
|
||||||
|
maven {
|
||||||
|
url = uri('https://m2.dv8tion.net/releases')
|
||||||
|
}
|
||||||
|
maven {
|
||||||
|
url = uri('https://jitpack.io')
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
minecraft {
|
|
||||||
version = "1.12.2-14.23.5.2847"
|
|
||||||
runDir = "run"
|
|
||||||
|
|
||||||
// the mappings can be changed at any time, and must be in the following format.
|
|
||||||
// snapshot_YYYYMMDD snapshot are built nightly.
|
|
||||||
// stable_# stables are built at the discretion of the MCP team.
|
|
||||||
// Use non-default mappings at your own risk. they may not always work.
|
|
||||||
// simply re-run your setup task after changing the mappings to update your workspace.
|
|
||||||
mappings = "stable_39"
|
|
||||||
// makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
//// MC version ////
|
||||||
// Compile against the JEI API but do not include it at runtime
|
// Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed
|
||||||
deobfProvided "mezz.jei:jei_${mc_version}:${jei_version}:api"
|
// that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied.
|
||||||
// At runtime, use the full JEI jar
|
// The userdev artifact is a special name and will get all sorts of transformations applied to it.
|
||||||
runtime "mezz.jei:jei_${mc_version}:${jei_version}"
|
minecraft "net.minecraftforge:forge:${project.mc_version}-${project.forge_version}"
|
||||||
|
//// MC version ////
|
||||||
deobfCompile "baubles:Baubles:${mc_version_short}:${baubles_version}"
|
implementation fg.deobf("curse.maven:baubles-${baubles_projectid}:${baubles_fileid}")
|
||||||
deobfCompile "antique-atlas:antiqueatlas:${mc_version}:${antique_atlas_version}"
|
implementation fg.deobf("mezz.jei:jei_${mc_version}:${jei_version}")
|
||||||
|
implementation fg.deobf("curse.maven:antique-atlas-${antiqueatlas_projectid}:${antiqueatlas_fileid}")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,20 +131,19 @@ task deobfJar(type: Jar) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
processResources {
|
processResources {
|
||||||
// this will ensure that this task is redone when the versions change.
|
// replace tokens in mcmod.info, and pack.mcmeta
|
||||||
inputs.property "version", project.version
|
|
||||||
inputs.property "mcversion", project.minecraft.version
|
|
||||||
|
|
||||||
// replace stuff in mcmod.info, nothing else
|
|
||||||
from(sourceSets.main.resources.srcDirs) {
|
from(sourceSets.main.resources.srcDirs) {
|
||||||
|
include 'pack.mcmeta'
|
||||||
include 'mcmod.info'
|
include 'mcmod.info'
|
||||||
|
|
||||||
// replace version and mcversion
|
|
||||||
expand 'version':project.version, 'mcversion':project.minecraft.version
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy everything else except the mcmod.info
|
duplicatesStrategy = 'include'
|
||||||
from(sourceSets.main.resources.srcDirs) {
|
}
|
||||||
exclude 'mcmod.info'
|
|
||||||
|
fancyGradle {
|
||||||
|
patches {
|
||||||
|
resources
|
||||||
|
coremods
|
||||||
|
asm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,22 @@
|
|||||||
# Sets default memory used for gradle commands. Can be overridden by user or command line properties.
|
# Sets default memory used for gradle commands. Can be overridden by user or command line properties.
|
||||||
# This is required to provide enough memory for the Minecraft decompilation process.
|
# This is required to provide enough memory for the Minecraft decompilation process.
|
||||||
org.gradle.jvmargs=-Xmx3G
|
org.gradle.jvmargs=-Xmx3G
|
||||||
|
mod_id=ebwizardry
|
||||||
mc_version=1.12.2
|
mc_version=1.12.2
|
||||||
mc_version_short=1.12
|
mc_version_short=1.12
|
||||||
jei_version=4.15.0.291
|
jei_version=4.15.0.291
|
||||||
baubles_version=1.5.2
|
baubles_version=1.5.2
|
||||||
antique_atlas_version=4.6.3
|
antique_atlas_version=4.6.3
|
||||||
|
forge_version=14.23.5.2860
|
||||||
|
mappings_version=39
|
||||||
|
mappings_channel=stable
|
||||||
|
mappings_mc_version=1.12
|
||||||
|
baubles_projectid=227083
|
||||||
|
baubles_fileid=2518667
|
||||||
|
jei_projectid=238222
|
||||||
|
artemislib_projectid=313590
|
||||||
|
artemislib_version=1.0.6
|
||||||
|
artemislib_fileid=2741812
|
||||||
|
antiqueatlas_projectid=227795
|
||||||
|
antiqueatlas_fileid=2823030
|
||||||
|
org.gradle.daemon=false
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip
|
|
||||||
|
|||||||
@@ -1,172 +1,232 @@
|
|||||||
#!/usr/bin/env sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright © 2015-2021 the original authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
##
|
#
|
||||||
## Gradle start up script for UN*X
|
# Gradle start up script for POSIX generated by Gradle.
|
||||||
##
|
#
|
||||||
|
# Important for running:
|
||||||
|
#
|
||||||
|
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||||
|
# noncompliant, but you have some other compliant shell such as ksh or
|
||||||
|
# bash, then to run this script, type that shell name before the whole
|
||||||
|
# command line, like:
|
||||||
|
#
|
||||||
|
# ksh Gradle
|
||||||
|
#
|
||||||
|
# Busybox and similar reduced shells will NOT work, because this script
|
||||||
|
# requires all of these POSIX shell features:
|
||||||
|
# * functions;
|
||||||
|
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||||
|
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||||
|
# * compound commands having a testable exit status, especially «case»;
|
||||||
|
# * various built-in commands including «command», «set», and «ulimit».
|
||||||
|
#
|
||||||
|
# Important for patching:
|
||||||
|
#
|
||||||
|
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||||
|
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||||
|
#
|
||||||
|
# The "traditional" practice of packing multiple parameters into a
|
||||||
|
# space-separated string is a well documented source of bugs and security
|
||||||
|
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||||
|
# options in "$@", and eventually passing that to Java.
|
||||||
|
#
|
||||||
|
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||||
|
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||||
|
# see the in-line comments for details.
|
||||||
|
#
|
||||||
|
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||||
|
# Darwin, MinGW, and NonStop.
|
||||||
|
#
|
||||||
|
# (3) This script is generated from the Groovy template
|
||||||
|
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
|
# within the Gradle project.
|
||||||
|
#
|
||||||
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
# Attempt to set APP_HOME
|
# Attempt to set APP_HOME
|
||||||
|
|
||||||
# Resolve links: $0 may be a link
|
# Resolve links: $0 may be a link
|
||||||
PRG="$0"
|
app_path=$0
|
||||||
# Need this for relative symlinks.
|
|
||||||
while [ -h "$PRG" ] ; do
|
# Need this for daisy-chained symlinks.
|
||||||
ls=`ls -ld "$PRG"`
|
while
|
||||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||||
if expr "$link" : '/.*' > /dev/null; then
|
[ -h "$app_path" ]
|
||||||
PRG="$link"
|
do
|
||||||
else
|
ls=$( ls -ld "$app_path" )
|
||||||
PRG=`dirname "$PRG"`"/$link"
|
link=${ls#*' -> '}
|
||||||
fi
|
case $link in #(
|
||||||
|
/*) app_path=$link ;; #(
|
||||||
|
*) app_path=$APP_HOME$link ;;
|
||||||
|
esac
|
||||||
done
|
done
|
||||||
SAVED="`pwd`"
|
|
||||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||||
APP_HOME="`pwd -P`"
|
|
||||||
cd "$SAVED" >/dev/null
|
|
||||||
|
|
||||||
APP_NAME="Gradle"
|
APP_NAME="Gradle"
|
||||||
APP_BASE_NAME=`basename "$0"`
|
APP_BASE_NAME=${0##*/}
|
||||||
|
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
DEFAULT_JVM_OPTS=""
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD="maximum"
|
MAX_FD=maximum
|
||||||
|
|
||||||
warn () {
|
warn () {
|
||||||
echo "$*"
|
echo "$*"
|
||||||
}
|
} >&2
|
||||||
|
|
||||||
die () {
|
die () {
|
||||||
echo
|
echo
|
||||||
echo "$*"
|
echo "$*"
|
||||||
echo
|
echo
|
||||||
exit 1
|
exit 1
|
||||||
}
|
} >&2
|
||||||
|
|
||||||
# OS specific support (must be 'true' or 'false').
|
# OS specific support (must be 'true' or 'false').
|
||||||
cygwin=false
|
cygwin=false
|
||||||
msys=false
|
msys=false
|
||||||
darwin=false
|
darwin=false
|
||||||
nonstop=false
|
nonstop=false
|
||||||
case "`uname`" in
|
case "$( uname )" in #(
|
||||||
CYGWIN* )
|
CYGWIN* ) cygwin=true ;; #(
|
||||||
cygwin=true
|
Darwin* ) darwin=true ;; #(
|
||||||
;;
|
MSYS* | MINGW* ) msys=true ;; #(
|
||||||
Darwin* )
|
NONSTOP* ) nonstop=true ;;
|
||||||
darwin=true
|
|
||||||
;;
|
|
||||||
MINGW* )
|
|
||||||
msys=true
|
|
||||||
;;
|
|
||||||
NONSTOP* )
|
|
||||||
nonstop=true
|
|
||||||
;;
|
|
||||||
esac
|
esac
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM.
|
# Determine the Java command to use to start the JVM.
|
||||||
if [ -n "$JAVA_HOME" ] ; then
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
# IBM's JDK on AIX uses strange locations for the executables
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||||
else
|
else
|
||||||
JAVACMD="$JAVA_HOME/bin/java"
|
JAVACMD=$JAVA_HOME/bin/java
|
||||||
fi
|
fi
|
||||||
if [ ! -x "$JAVACMD" ] ; then
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
Please set the JAVA_HOME variable in your environment to match the
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD="java"
|
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.
|
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
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
MAX_FD_LIMIT=`ulimit -H -n`
|
case $MAX_FD in #(
|
||||||
if [ $? -eq 0 ] ; then
|
max*)
|
||||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
MAX_FD="$MAX_FD_LIMIT"
|
warn "Could not query maximum file descriptor limit"
|
||||||
fi
|
esac
|
||||||
ulimit -n $MAX_FD
|
case $MAX_FD in #(
|
||||||
if [ $? -ne 0 ] ; then
|
'' | soft) :;; #(
|
||||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
*)
|
||||||
fi
|
ulimit -n "$MAX_FD" ||
|
||||||
else
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# For Darwin, add options to specify how the application appears in the dock
|
|
||||||
if $darwin; then
|
|
||||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
|
||||||
fi
|
|
||||||
|
|
||||||
# For Cygwin, switch paths to Windows format before running java
|
|
||||||
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`
|
|
||||||
SEP=""
|
|
||||||
for dir in $ROOTDIRSRAW ; do
|
|
||||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
|
||||||
SEP="|"
|
|
||||||
done
|
|
||||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
|
||||||
# Add a user-defined pattern to the cygpath arguments
|
|
||||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
|
||||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
|
||||||
fi
|
|
||||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
|
||||||
i=0
|
|
||||||
for arg in "$@" ; do
|
|
||||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
|
||||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
|
||||||
|
|
||||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
|
||||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
|
||||||
else
|
|
||||||
eval `echo args$i`="\"$arg\""
|
|
||||||
fi
|
|
||||||
i=$((i+1))
|
|
||||||
done
|
|
||||||
case $i in
|
|
||||||
(0) set -- ;;
|
|
||||||
(1) set -- "$args0" ;;
|
|
||||||
(2) set -- "$args0" "$args1" ;;
|
|
||||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
|
||||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
|
||||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
|
||||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
|
||||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
|
||||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
|
||||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Escape application args
|
# Collect all arguments for the java command, stacking in reverse order:
|
||||||
save () {
|
# * args from the command line
|
||||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
# * the main class name
|
||||||
echo " "
|
# * -classpath
|
||||||
}
|
# * -D...appname settings
|
||||||
APP_ARGS=$(save "$@")
|
# * --module-path (only if needed)
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||||
|
|
||||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
if "$cygwin" || "$msys" ; then
|
||||||
|
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||||
|
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||||
|
|
||||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
|
||||||
cd "$(dirname "$0")"
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
for arg do
|
||||||
|
if
|
||||||
|
case $arg in #(
|
||||||
|
-*) false ;; # don't mess with options #(
|
||||||
|
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||||
|
[ -e "$t" ] ;; #(
|
||||||
|
*) false ;;
|
||||||
|
esac
|
||||||
|
then
|
||||||
|
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||||
|
fi
|
||||||
|
# Roll the args list around exactly as many times as the number of
|
||||||
|
# args, so each arg winds up back in the position where it started, but
|
||||||
|
# possibly modified.
|
||||||
|
#
|
||||||
|
# NB: a `for` loop captures its iteration list before it begins, so
|
||||||
|
# changing the positional parameters here affects neither the number of
|
||||||
|
# iterations, nor the values presented in `arg`.
|
||||||
|
shift # remove old arg
|
||||||
|
set -- "$@" "$arg" # push replacement arg
|
||||||
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Collect all arguments for the java command;
|
||||||
|
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||||
|
# shell script including quotes and variable substitutions, so put them in
|
||||||
|
# double quotes to make sure that they get re-expanded; and
|
||||||
|
# * put everything else in single quotes, so that it's not re-expanded.
|
||||||
|
|
||||||
|
set -- \
|
||||||
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
|
-classpath "$CLASSPATH" \
|
||||||
|
org.gradle.wrapper.GradleWrapperMain \
|
||||||
|
"$@"
|
||||||
|
|
||||||
|
# Use "xargs" to parse quoted args.
|
||||||
|
#
|
||||||
|
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||||
|
#
|
||||||
|
# In Bash we could simply go:
|
||||||
|
#
|
||||||
|
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||||
|
# set -- "${ARGS[@]}" "$@"
|
||||||
|
#
|
||||||
|
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||||
|
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||||
|
# character that might be a shell metacharacter, then use eval to reverse
|
||||||
|
# that process (while maintaining the separation between arguments), and wrap
|
||||||
|
# the whole thing up as a single "set" statement.
|
||||||
|
#
|
||||||
|
# This will of course break if any of these variables contains a newline or
|
||||||
|
# an unmatched quote.
|
||||||
|
#
|
||||||
|
|
||||||
|
eval "set -- $(
|
||||||
|
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||||
|
xargs -n1 |
|
||||||
|
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||||
|
tr '\n' ' '
|
||||||
|
)" '"$@"'
|
||||||
|
|
||||||
exec "$JAVACMD" "$@"
|
exec "$JAVACMD" "$@"
|
||||||
Vendored
+24
-19
@@ -1,3 +1,19 @@
|
|||||||
|
@rem
|
||||||
|
@rem Copyright 2015 the original author or authors.
|
||||||
|
@rem
|
||||||
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@rem you may not use this file except in compliance with the License.
|
||||||
|
@rem You may obtain a copy of the License at
|
||||||
|
@rem
|
||||||
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@rem
|
||||||
|
@rem Unless required by applicable law or agreed to in writing, software
|
||||||
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@rem See the License for the specific language governing permissions and
|
||||||
|
@rem limitations under the License.
|
||||||
|
@rem
|
||||||
|
|
||||||
@if "%DEBUG%" == "" @echo off
|
@if "%DEBUG%" == "" @echo off
|
||||||
@rem ##########################################################################
|
@rem ##########################################################################
|
||||||
@rem
|
@rem
|
||||||
@@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=.
|
|||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
|
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||||
|
|
||||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
@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 DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
@rem Find java.exe
|
@rem Find java.exe
|
||||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
set JAVA_EXE=java.exe
|
set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if "%ERRORLEVEL%" == "0" goto init
|
if "%ERRORLEVEL%" == "0" goto execute
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
@@ -35,7 +54,7 @@ goto fail
|
|||||||
set JAVA_HOME=%JAVA_HOME:"=%
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
if exist "%JAVA_EXE%" goto init
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
@@ -45,28 +64,14 @@ echo location of your Java installation.
|
|||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:init
|
|
||||||
@rem Get command-line arguments, handling Windows variants
|
|
||||||
|
|
||||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
|
||||||
|
|
||||||
:win9xME_args
|
|
||||||
@rem Slurp the command line arguments.
|
|
||||||
set CMD_LINE_ARGS=
|
|
||||||
set _SKIP=2
|
|
||||||
|
|
||||||
:win9xME_args_slurp
|
|
||||||
if "x%~1" == "x" goto execute
|
|
||||||
|
|
||||||
set CMD_LINE_ARGS=%*
|
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
||||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
@rem Execute Gradle
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
|||||||
@@ -156,6 +156,12 @@ public final class Settings {
|
|||||||
public Pair<ResourceLocation, Short>[] treeBlocks = parseItemMetaStrings(DEFAULT_TREE_BLOCKS);
|
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. */
|
/** <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 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. */
|
/** <b>[Server-only]</b> List of dimension ids in which to generate crystal ore. */
|
||||||
public int[] oreDimensions = {0};
|
public int[] oreDimensions = {0};
|
||||||
/** <b>[Server-only]</b> List of dimension ids in which to generate crystal flowers. */
|
/** <b>[Server-only]</b> List of dimension ids in which to generate crystal flowers. */
|
||||||
@@ -192,12 +198,21 @@ public final class Settings {
|
|||||||
public boolean playerBlockDamage = true;
|
public boolean playerBlockDamage = true;
|
||||||
/** <b>[Server-only]</b> Whether spells cast by dispensers can destroy blocks in the world. */
|
/** <b>[Server-only]</b> Whether spells cast by dispensers can destroy blocks in the world. */
|
||||||
public boolean dispenserBlockDamage = true;
|
public boolean dispenserBlockDamage = true;
|
||||||
|
/** <b>[Server-only]</b> Whether damage should be registered with the old system (wizardry_magic/indirect_wizardry_magic) prefixed damage with the elements like
|
||||||
|
* necromancy_indirect_wizardry_magic, necromancy_wizardry_magic*/
|
||||||
|
public boolean damageTypePerElement = false;
|
||||||
|
/** <b>[Server-only]</b> Whether spell books are consumed when they are bound to a wand.*/
|
||||||
|
public boolean singleUseSpellBooks = false;
|
||||||
|
/** <b>[Server-only]</b> Whether to prevent binding the same spell to a wand multiple times*/
|
||||||
|
public boolean preventBindingSameSpellTwiceToWands = false;
|
||||||
/** <b>[Server-only]</b> Whether to revert to the old wand upgrade system, which only requires tomes of arcana. */
|
/** <b>[Server-only]</b> Whether to revert to the old wand upgrade system, which only requires tomes of arcana. */
|
||||||
public boolean legacyWandLevelling = false;
|
public boolean legacyWandLevelling = false;
|
||||||
/** <b>[Server-only]</b> Whether to tweak the blindness effect to reduce follow distance when used on non-players. */
|
/** <b>[Server-only]</b> Whether to tweak the blindness effect to reduce follow distance when used on non-players. */
|
||||||
public boolean blindnessTweak = true;
|
public boolean blindnessTweak = true;
|
||||||
/** <b>[Server-only]</b> Whether using bonemeal on grass blocks has a chance to grow crystal flowers. */
|
/** <b>[Server-only]</b> Whether using bonemeal on grass blocks has a chance to grow crystal flowers. */
|
||||||
public boolean bonemealGrowsCrystalFlowers = true;
|
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. */
|
/** <b>[Server-only]</b> Whether to enable Wizardry mob loot injection. Allows an easier switch instead of blacklisting all entities. */
|
||||||
public boolean injectMobDrops = true;
|
public boolean injectMobDrops = true;
|
||||||
/**
|
/**
|
||||||
@@ -379,6 +394,9 @@ public final class Settings {
|
|||||||
public boolean showSpellHUD = true;
|
public boolean showSpellHUD = true;
|
||||||
/** <b>[Client-only]</b> Whether to show the charge meter when charging up a spell. */
|
/** <b>[Client-only]</b> Whether to show the charge meter when charging up a spell. */
|
||||||
public boolean showChargeMeter = true;
|
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. */
|
/** <b>[Client-only]</b> The position of the spell HUD. */
|
||||||
public GuiPosition spellHUDPosition = GuiPosition.BOTTOM_LEFT;
|
public GuiPosition spellHUDPosition = GuiPosition.BOTTOM_LEFT;
|
||||||
|
|
||||||
@@ -614,6 +632,29 @@ public final class Settings {
|
|||||||
dispenserBlockDamage = property.getBoolean();
|
dispenserBlockDamage = property.getBoolean();
|
||||||
propOrder.add(property.getName());
|
propOrder.add(property.getName());
|
||||||
|
|
||||||
|
property = config.get(GAMEPLAY_CATEGORY, "damageTypePerElement", false,
|
||||||
|
"Whether damage should be registered with the old system (wizardry_magic/indirect_wizardry_magic) prefixed damage with the elements like "
|
||||||
|
+ "necromancy_indirect_wizardry_magic, necromancy_wizardry_magic. This is disabled by default to not break existing modpacks."
|
||||||
|
+ "The intention of this setting is to allow differentiating various damage types for e.g. the Distinct Damage Descriptions mod");
|
||||||
|
property.setLanguageKey("config." + Wizardry.MODID + ".damage_type_per_element");
|
||||||
|
Wizardry.proxy.setToNamedBooleanEntry(property);
|
||||||
|
damageTypePerElement = property.getBoolean();
|
||||||
|
propOrder.add(property.getName());
|
||||||
|
|
||||||
|
property = config.get(GAMEPLAY_CATEGORY, "singleUseSpellBooks", false,
|
||||||
|
"Whether spell books are consumed when they are bound to a wand.");
|
||||||
|
property.setLanguageKey("config." + Wizardry.MODID + ".single_use_spell_books");
|
||||||
|
Wizardry.proxy.setToNamedBooleanEntry(property);
|
||||||
|
singleUseSpellBooks = property.getBoolean();
|
||||||
|
propOrder.add(property.getName());
|
||||||
|
|
||||||
|
property = config.get(GAMEPLAY_CATEGORY, "preventBindingSameSpellTwiceToWands", false,
|
||||||
|
"Whether to prevent binding the same spell to a wand multiple times");
|
||||||
|
property.setLanguageKey("config." + Wizardry.MODID + ".prevent_binding_same_spell_twice_to_wands");
|
||||||
|
Wizardry.proxy.setToNamedBooleanEntry(property);
|
||||||
|
preventBindingSameSpellTwiceToWands = property.getBoolean();
|
||||||
|
propOrder.add(property.getName());
|
||||||
|
|
||||||
property = config.get(GAMEPLAY_CATEGORY, "playersMoveEachOther", true,
|
property = config.get(GAMEPLAY_CATEGORY, "playersMoveEachOther", true,
|
||||||
"Whether to allow players to move other players around using magic.");
|
"Whether to allow players to move other players around using magic.");
|
||||||
property.setLanguageKey("config." + Wizardry.MODID + ".players_move_each_other");
|
property.setLanguageKey("config." + Wizardry.MODID + ".players_move_each_other");
|
||||||
@@ -665,6 +706,13 @@ public final class Settings {
|
|||||||
bonemealGrowsCrystalFlowers = property.getBoolean();
|
bonemealGrowsCrystalFlowers = property.getBoolean();
|
||||||
propOrder.add(property.getName());
|
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!
|
checkForRedundantOptions(GAMEPLAY_CATEGORY, propOrder); // Must be before the order is set!
|
||||||
config.setCategoryPropertyOrder(GAMEPLAY_CATEGORY, propOrder);
|
config.setCategoryPropertyOrder(GAMEPLAY_CATEGORY, propOrder);
|
||||||
|
|
||||||
@@ -923,6 +971,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!
|
checkForRedundantOptions(TWEAKS_CATEGORY, propOrder); // Must be before the order is set!
|
||||||
config.setCategoryPropertyOrder(TWEAKS_CATEGORY, propOrder);
|
config.setCategoryPropertyOrder(TWEAKS_CATEGORY, propOrder);
|
||||||
|
|
||||||
@@ -1112,6 +1204,13 @@ public final class Settings {
|
|||||||
showChargeMeter = property.getBoolean();
|
showChargeMeter = property.getBoolean();
|
||||||
propOrder.add(property.getName());
|
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 = 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");
|
property.setLanguageKey("config." + Wizardry.MODID + ".spell_hud_position");
|
||||||
spellHUDPosition = GuiPosition.fromName(property.getString());
|
spellHUDPosition = GuiPosition.fromName(property.getString());
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import electroblob.wizardry.registry.WizardryItems;
|
|||||||
import electroblob.wizardry.registry.WizardryLoot;
|
import electroblob.wizardry.registry.WizardryLoot;
|
||||||
import electroblob.wizardry.registry.WizardrySounds;
|
import electroblob.wizardry.registry.WizardrySounds;
|
||||||
import electroblob.wizardry.spell.Spell;
|
import electroblob.wizardry.spell.Spell;
|
||||||
|
import electroblob.wizardry.util.SpellNetworkIDSorter;
|
||||||
import electroblob.wizardry.util.SpellProperties;
|
import electroblob.wizardry.util.SpellProperties;
|
||||||
import electroblob.wizardry.util.WandHelper;
|
import electroblob.wizardry.util.WandHelper;
|
||||||
import electroblob.wizardry.worldgen.WorldGenCrystalFlower;
|
import electroblob.wizardry.worldgen.WorldGenCrystalFlower;
|
||||||
@@ -81,7 +82,7 @@ public class Wizardry {
|
|||||||
* 1.x.x represents Minecraft 1.7.x versions, 2.x.x represents Minecraft 1.10.x versions, 3.x.x represents Minecraft
|
* 1.x.x represents Minecraft 1.7.x versions, 2.x.x represents Minecraft 1.10.x versions, 3.x.x represents Minecraft
|
||||||
* 1.11.x versions, and so on.
|
* 1.11.x versions, and so on.
|
||||||
*/
|
*/
|
||||||
public static final String VERSION = "4.3.5";
|
public static final String VERSION = "4.3.13";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Json file used by Forge's built-in <a href="https://mcforge.readthedocs.io/en/1.12.x/gettingstarted/autoupdate/">update checker</a>.
|
* Json file used by Forge's built-in <a href="https://mcforge.readthedocs.io/en/1.12.x/gettingstarted/autoupdate/">update checker</a>.
|
||||||
@@ -127,8 +128,6 @@ public class Wizardry {
|
|||||||
|
|
||||||
logger = event.getModLog();
|
logger = event.getModLog();
|
||||||
|
|
||||||
proxy.registerResourceReloadListeners();
|
|
||||||
|
|
||||||
configDirectory = new File(event.getModConfigurationDirectory(), Wizardry.MODID);
|
configDirectory = new File(event.getModConfigurationDirectory(), Wizardry.MODID);
|
||||||
settings.initConfig(event);
|
settings.initConfig(event);
|
||||||
|
|
||||||
@@ -161,6 +160,7 @@ public class Wizardry {
|
|||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void init(FMLInitializationEvent event){
|
public void init(FMLInitializationEvent event){
|
||||||
|
proxy.registerResourceReloadListeners();
|
||||||
|
|
||||||
settings.initConfigExtras();
|
settings.initConfigExtras();
|
||||||
|
|
||||||
@@ -202,6 +202,8 @@ public class Wizardry {
|
|||||||
public void postInit(FMLPostInitializationEvent event){
|
public void postInit(FMLPostInitializationEvent event){
|
||||||
proxy.initialiseLayers();
|
proxy.initialiseLayers();
|
||||||
proxy.initialiseAnimations();
|
proxy.initialiseAnimations();
|
||||||
|
|
||||||
|
SpellNetworkIDSorter.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@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
|
// 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|))
|
// Angle between a and b = acos((a.b) / (|a|*|b|))
|
||||||
double angle = Math.acos(vec.dotProduct(event.getEntity().getLookVec()) / vec.length());
|
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 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){
|
if(angle > 0.4 * Math.PI){
|
||||||
((EntityLiving)event.getEntityLiving()).setAttackTarget(null);
|
((EntityLiving)event.getEntityLiving()).setAttackTarget(null);
|
||||||
@@ -269,7 +268,7 @@ public final class WizardryEventHandler {
|
|||||||
// Fireskin
|
// Fireskin
|
||||||
if(event.getEntityLiving().isPotionActive(WizardryPotions.fireskin)
|
if(event.getEntityLiving().isPotionActive(WizardryPotions.fireskin)
|
||||||
&& !MagicDamage.isEntityImmune(DamageType.FIRE, event.getEntityLiving()))
|
&& !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
|
// Ice Shroud
|
||||||
if(event.getEntityLiving().isPotionActive(WizardryPotions.ice_shroud)
|
if(event.getEntityLiving().isPotionActive(WizardryPotions.ice_shroud)
|
||||||
@@ -307,7 +306,7 @@ public final class WizardryEventHandler {
|
|||||||
PotionEffect effect = event.getEntityLiving().getActivePotionEffect(WizardryPotions.ward);
|
PotionEffect effect = event.getEntityLiving().getActivePotionEffect(WizardryPotions.ward);
|
||||||
|
|
||||||
if(effect != null && event.getSource().isMagicDamage()){
|
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
|
// Flaming and freezing swords
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package electroblob.wizardry.client;
|
package electroblob.wizardry.client;
|
||||||
|
|
||||||
import electroblob.wizardry.CommonProxy;
|
import electroblob.wizardry.CommonProxy;
|
||||||
|
import electroblob.wizardry.Settings;
|
||||||
import electroblob.wizardry.Wizardry;
|
import electroblob.wizardry.Wizardry;
|
||||||
import electroblob.wizardry.block.BlockBookshelf;
|
import electroblob.wizardry.block.BlockBookshelf;
|
||||||
import electroblob.wizardry.client.animation.ActionAnimation;
|
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.model.ModelWizardArmour;
|
||||||
import electroblob.wizardry.client.particle.*;
|
import electroblob.wizardry.client.particle.*;
|
||||||
import electroblob.wizardry.client.particle.ParticleWizardry.IWizardryParticleFactory;
|
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.*;
|
||||||
import electroblob.wizardry.client.renderer.entity.layers.*;
|
import electroblob.wizardry.client.renderer.entity.layers.*;
|
||||||
import electroblob.wizardry.client.renderer.overlay.RenderBlinkEffect;
|
import electroblob.wizardry.client.renderer.overlay.RenderBlinkEffect;
|
||||||
@@ -164,7 +166,8 @@ public class ClientProxy extends CommonProxy {
|
|||||||
IResourceManager manager = Minecraft.getMinecraft().getResourceManager();
|
IResourceManager manager = Minecraft.getMinecraft().getResourceManager();
|
||||||
if(manager instanceof IReloadableResourceManager){
|
if(manager instanceof IReloadableResourceManager){
|
||||||
((IReloadableResourceManager)manager).registerReloadListener(GuiSpellDisplay::loadSkins);
|
((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(LayerMindControl::new);
|
||||||
LayerTiledOverlay.initialiseLayers(LayerSummonAnimation::new);
|
LayerTiledOverlay.initialiseLayers(LayerSummonAnimation::new);
|
||||||
LayerTiledOverlay.initialiseLayers(LayerDisintegrateAnimation::new);
|
LayerTiledOverlay.initialiseLayers(LayerDisintegrateAnimation::new);
|
||||||
|
LayerTiledOverlay.initialiseLayers(LayerOak::new);
|
||||||
|
LayerTiledOverlay.initialiseLayers(LayerIron::new);
|
||||||
|
LayerTiledOverlay.initialiseLayers(LayerDiamond::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -766,6 +772,7 @@ public class ClientProxy extends CommonProxy {
|
|||||||
|
|
||||||
RenderingRegistry.registerEntityRenderingHandler(EntityIceGiant.class, RenderIceGiant::new);
|
RenderingRegistry.registerEntityRenderingHandler(EntityIceGiant.class, RenderIceGiant::new);
|
||||||
RenderingRegistry.registerEntityRenderingHandler(EntityPhoenix.class, RenderPhoenix::new);
|
RenderingRegistry.registerEntityRenderingHandler(EntityPhoenix.class, RenderPhoenix::new);
|
||||||
|
RenderingRegistry.registerEntityRenderingHandler(EntitySpectralGolem.class, RenderSpectralGolem::new);
|
||||||
|
|
||||||
// Projectiles
|
// Projectiles
|
||||||
RenderingRegistry.registerEntityRenderingHandler(EntityMagicMissile.class, manager -> new RenderMagicArrow(manager,
|
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));
|
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,
|
RenderingRegistry.registerEntityRenderingHandler(EntityFlamecatcherArrow.class, manager -> new RenderMagicArrow(manager,
|
||||||
new ResourceLocation(Wizardry.MODID, "textures/entity/flamecatcher_arrow.png"), false, 8, 2.0, 16, 5, true));
|
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);
|
RenderingRegistry.registerEntityRenderingHandler(EntityForceArrow.class, RenderForceArrow::new);
|
||||||
|
|
||||||
|
|||||||
@@ -3,10 +3,7 @@ package electroblob.wizardry.client;
|
|||||||
import electroblob.wizardry.client.renderer.overlay.RenderBlinkEffect;
|
import electroblob.wizardry.client.renderer.overlay.RenderBlinkEffect;
|
||||||
import electroblob.wizardry.data.DispenserCastingData;
|
import electroblob.wizardry.data.DispenserCastingData;
|
||||||
import electroblob.wizardry.data.SpellEmitterData;
|
import electroblob.wizardry.data.SpellEmitterData;
|
||||||
import electroblob.wizardry.item.ItemArtefact;
|
import electroblob.wizardry.item.*;
|
||||||
import electroblob.wizardry.item.ItemFlamecatcher;
|
|
||||||
import electroblob.wizardry.item.ItemSpectralBow;
|
|
||||||
import electroblob.wizardry.item.ItemWand;
|
|
||||||
import electroblob.wizardry.potion.PotionSlowTime;
|
import electroblob.wizardry.potion.PotionSlowTime;
|
||||||
import electroblob.wizardry.registry.WizardryItems;
|
import electroblob.wizardry.registry.WizardryItems;
|
||||||
import electroblob.wizardry.registry.WizardryPotions;
|
import electroblob.wizardry.registry.WizardryPotions;
|
||||||
@@ -120,6 +117,7 @@ public final class WizardryClientEventHandler {
|
|||||||
Minecraft.getMinecraft().player.prevRotationPitch = 0;
|
Minecraft.getMinecraft().player.prevRotationPitch = 0;
|
||||||
Minecraft.getMinecraft().player.rotationYaw = 0;
|
Minecraft.getMinecraft().player.rotationYaw = 0;
|
||||||
Minecraft.getMinecraft().player.rotationPitch = 0;
|
Minecraft.getMinecraft().player.rotationPitch = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +134,7 @@ public final class WizardryClientEventHandler {
|
|||||||
|
|
||||||
if(ItemArtefact.isArtefactActive(event.getEntityPlayer(), WizardryItems.charm_move_speed)
|
if(ItemArtefact.isArtefactActive(event.getEntityPlayer(), WizardryItems.charm_move_speed)
|
||||||
&& event.getEntityPlayer().isHandActive()
|
&& event.getEntityPlayer().isHandActive()
|
||||||
&& event.getEntityPlayer().getActiveItemStack().getItem() instanceof ItemWand){
|
&& event.getEntityPlayer().getActiveItemStack().getItem() instanceof ISpellCastingItem){
|
||||||
// Normally speed is set to 20% when using items, this makes it 80%
|
// Normally speed is set to 20% when using items, this makes it 80%
|
||||||
event.getMovementInput().moveStrafe *= 4;
|
event.getMovementInput().moveStrafe *= 4;
|
||||||
event.getMovementInput().moveForward *= 4;
|
event.getMovementInput().moveForward *= 4;
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ public class GuiArcaneWorkbench extends GuiContainer {
|
|||||||
private ContainerArcaneWorkbench arcaneWorkbenchContainer;
|
private ContainerArcaneWorkbench arcaneWorkbenchContainer;
|
||||||
|
|
||||||
private GuiButton applyBtn;
|
private GuiButton applyBtn;
|
||||||
|
private GuiButton clearBtn;
|
||||||
private GuiButton[] sortButtons = new GuiButton[3];
|
private GuiButton[] sortButtons = new GuiButton[3];
|
||||||
|
|
||||||
private GuiTextField searchField;
|
private GuiTextField searchField;
|
||||||
@@ -126,6 +127,7 @@ public class GuiArcaneWorkbench extends GuiContainer {
|
|||||||
|
|
||||||
this.buttonList.clear();
|
this.buttonList.clear();
|
||||||
this.buttonList.add(this.applyBtn = new GuiButtonApply(0, this.width / 2 + 64, this.height / 2 + 3));
|
this.buttonList.add(this.applyBtn = new GuiButtonApply(0, this.width / 2 + 64, this.height / 2 + 3));
|
||||||
|
this.buttonList.add(this.clearBtn = new GuiButtonClear(0, this.width / 2 + 64, this.height / 2 - 16));
|
||||||
this.buttonList.add(sortButtons[0] = new GuiButtonSpellSort(1, this.guiLeft - 44, this.guiTop + 8, ISpellSortable.SortType.TIER, arcaneWorkbenchContainer, this));
|
this.buttonList.add(sortButtons[0] = new GuiButtonSpellSort(1, this.guiLeft - 44, this.guiTop + 8, ISpellSortable.SortType.TIER, arcaneWorkbenchContainer, this));
|
||||||
this.buttonList.add(sortButtons[1] = new GuiButtonSpellSort(2, this.guiLeft - 31, this.guiTop + 8, ISpellSortable.SortType.ELEMENT, arcaneWorkbenchContainer, this));
|
this.buttonList.add(sortButtons[1] = new GuiButtonSpellSort(2, this.guiLeft - 31, this.guiTop + 8, ISpellSortable.SortType.ELEMENT, arcaneWorkbenchContainer, this));
|
||||||
this.buttonList.add(sortButtons[2] = new GuiButtonSpellSort(3, this.guiLeft - 18, this.guiTop + 8, ISpellSortable.SortType.ALPHABETICAL, arcaneWorkbenchContainer, this));
|
this.buttonList.add(sortButtons[2] = new GuiButtonSpellSort(3, this.guiLeft - 18, this.guiTop + 8, ISpellSortable.SortType.ALPHABETICAL, arcaneWorkbenchContainer, this));
|
||||||
@@ -205,6 +207,7 @@ public class GuiArcaneWorkbench extends GuiContainer {
|
|||||||
|
|
||||||
// Show/hide the relevant gui elements
|
// Show/hide the relevant gui elements
|
||||||
this.applyBtn.enabled = centreSlot.getHasStack();
|
this.applyBtn.enabled = centreSlot.getHasStack();
|
||||||
|
this.clearBtn.enabled = centreSlot.getHasStack() && centreSlot.getStack().getItem() instanceof IWorkbenchItem && ((IWorkbenchItem) centreSlot.getStack().getItem()).isClearable();
|
||||||
for(GuiButton button : this.sortButtons) button.visible = arcaneWorkbenchContainer.hasBookshelves();
|
for(GuiButton button : this.sortButtons) button.visible = arcaneWorkbenchContainer.hasBookshelves();
|
||||||
this.searchField.setVisible(arcaneWorkbenchContainer.hasBookshelves());
|
this.searchField.setVisible(arcaneWorkbenchContainer.hasBookshelves());
|
||||||
|
|
||||||
@@ -444,6 +447,17 @@ public class GuiArcaneWorkbench extends GuiContainer {
|
|||||||
animationTimer = 20;
|
animationTimer = 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(button == clearBtn){
|
||||||
|
// Packet building
|
||||||
|
IMessage msg = new PacketControlInput.Message(PacketControlInput.ControlType.CLEAR_BUTTON);
|
||||||
|
WizardryPacketHandler.net.sendToServer(msg);
|
||||||
|
// Sound
|
||||||
|
Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(
|
||||||
|
WizardrySounds.BLOCK_ARCANE_WORKBENCH_SPELLBIND, 0.8f));
|
||||||
|
// Animation
|
||||||
|
animationTimer = 20;
|
||||||
|
}
|
||||||
|
|
||||||
if(button instanceof GuiButtonSpellSort) this.arcaneWorkbenchContainer.setSortType(((GuiButtonSpellSort)button).sortType);
|
if(button instanceof GuiButtonSpellSort) this.arcaneWorkbenchContainer.setSortType(((GuiButtonSpellSort)button).sortType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1006,4 +1020,36 @@ public class GuiArcaneWorkbench extends GuiContainer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class GuiButtonClear extends GuiButton {
|
||||||
|
|
||||||
|
public GuiButtonClear(int id, int x, int y){
|
||||||
|
super(id, x, y, 16, 16, I18n.format("container." + Wizardry.MODID + ":arcane_workbench.clear"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawButton(Minecraft minecraft, int mouseX, int mouseY, float partialTicks){
|
||||||
|
|
||||||
|
// Whether the button is highlighted
|
||||||
|
this.hovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height;
|
||||||
|
|
||||||
|
int k = 72;
|
||||||
|
int l = 236;
|
||||||
|
//int colour = 14737632;
|
||||||
|
|
||||||
|
if(this.enabled){
|
||||||
|
if(this.hovered){
|
||||||
|
k += this.width * 2;
|
||||||
|
//colour = 16777120;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
k += this.width;
|
||||||
|
//colour = 10526880;
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawingUtils.drawTexturedRect(this.x, this.y, k, l, this.width, this.height, TEXTURE_WIDTH, TEXTURE_HEIGHT);
|
||||||
|
//this.drawCenteredString(minecraft.fontRenderer, this.displayString, this.x + this.width / 2,
|
||||||
|
// this.y + (this.height - 8) / 2, colour);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -33,9 +33,13 @@ import java.awt.*;
|
|||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.util.List;
|
|
||||||
import java.util.*;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GUI class for the wizard's handbook. Like any GUI class, this is instantiated each time the book is opened. As of
|
* GUI class for the wizard's handbook. Like any GUI class, this is instantiated each time the book is opened. As of
|
||||||
@@ -55,6 +59,8 @@ public class GuiWizardHandbook extends GuiScreen {
|
|||||||
|
|
||||||
private static final ResourceLocation DEFAULT = new ResourceLocation(Wizardry.MODID, "texts/handbook_en_us.json");
|
private static final ResourceLocation DEFAULT = new ResourceLocation(Wizardry.MODID, "texts/handbook_en_us.json");
|
||||||
|
|
||||||
|
private static List<String> ADDONS = new ArrayList<>();
|
||||||
|
|
||||||
static final ResourceLocation texture = new ResourceLocation(Wizardry.MODID, "textures/gui/handbook/handbook.png");
|
static final ResourceLocation texture = new ResourceLocation(Wizardry.MODID, "textures/gui/handbook/handbook.png");
|
||||||
|
|
||||||
/** Global Gson instance for the handbook. */
|
/** Global Gson instance for the handbook. */
|
||||||
@@ -406,9 +412,10 @@ public class GuiWizardHandbook extends GuiScreen {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IResource handbookFile = getHandbookResource(manager);
|
// IResource handbookFile = getHandbookResource(manager);
|
||||||
|
List<IResource> handbookFiles = getHandbookResource(manager);
|
||||||
|
|
||||||
if(handbookFile != null){
|
if(!handbookFiles.isEmpty()){
|
||||||
|
|
||||||
// Wipes all the maps before repopulating them
|
// Wipes all the maps before repopulating them
|
||||||
images.clear();
|
images.clear();
|
||||||
@@ -418,28 +425,31 @@ public class GuiWizardHandbook extends GuiScreen {
|
|||||||
|
|
||||||
bookmarkSection = null; // Also need to wipe the reference to the old bookmarked section
|
bookmarkSection = null; // Also need to wipe the reference to the old bookmarked section
|
||||||
|
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(handbookFile.getInputStream(), StandardCharsets.UTF_8));
|
for (IResource handbookFile : handbookFiles) {
|
||||||
|
|
||||||
JsonElement je = gson.fromJson(reader, JsonElement.class);
|
BufferedReader reader = new BufferedReader(new InputStreamReader(handbookFile.getInputStream(), StandardCharsets.UTF_8));
|
||||||
JsonObject json = je.getAsJsonObject();
|
|
||||||
|
|
||||||
JsonUtils.getJsonObject(json, "colours").entrySet().forEach(e -> colours.put(e.getKey(),
|
JsonElement je = gson.fromJson(reader, JsonElement.class);
|
||||||
Color.decode(e.getValue().getAsString()).getRGB()));
|
JsonObject json = je.getAsJsonObject();
|
||||||
|
|
||||||
// Repopulates the remaining maps
|
JsonUtils.getJsonObject(json, "colours").entrySet().forEach(e -> colours.put(e.getKey(),
|
||||||
Image.populate(images, json);
|
Color.decode(e.getValue().getAsString()).getRGB()));
|
||||||
CraftingRecipe.populate(recipes, json);
|
|
||||||
Section.populate(sections, json);
|
|
||||||
|
|
||||||
sectionList = Collections.unmodifiableList(new ArrayList<>(sections.values()));
|
// Repopulates the remaining maps
|
||||||
|
Image.populate(images, json);
|
||||||
|
CraftingRecipe.populate(recipes, json);
|
||||||
|
Section.populate(sections, json);
|
||||||
|
|
||||||
if(sections.isEmpty()){
|
sectionList = Collections.unmodifiableList(new ArrayList<>(sections.values()));
|
||||||
Wizardry.logger.warn("Handbook has no sections! Aborting loading...");
|
|
||||||
return;
|
if(sections.isEmpty()){
|
||||||
|
Wizardry.logger.warn("Handbook has no sections! Aborting loading...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bookmarkSection = JsonUtils.getString(json, "bookmark_start_section");
|
||||||
|
if(!sections.containsKey(bookmarkSection)) throw new JsonSyntaxException("Section with id " + bookmarkSection + " is undefined");
|
||||||
}
|
}
|
||||||
|
|
||||||
bookmarkSection = JsonUtils.getString(json, "bookmark_start_section");
|
|
||||||
if(!sections.containsKey(bookmarkSection)) throw new JsonSyntaxException("Section with id " + bookmarkSection + " is undefined");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The first resource load on startup is done before the packet handler is loaded
|
// The first resource load on startup is done before the packet handler is loaded
|
||||||
@@ -455,16 +465,17 @@ public class GuiWizardHandbook extends GuiScreen {
|
|||||||
* @param manager The resource manager instance to use.
|
* @param manager The resource manager instance to use.
|
||||||
* @return The handbook JSON file, as an IResource, or null if it was not found.
|
* @return The handbook JSON file, as an IResource, or null if it was not found.
|
||||||
*/
|
*/
|
||||||
private static IResource getHandbookResource(IResourceManager manager){
|
private static List<IResource> getHandbookResource(IResourceManager manager){
|
||||||
|
|
||||||
// TODO: Implement resource pack stacking to allow addon mods and texture packs to add/overwrite content
|
// TODO: Implement resource pack stacking to allow addon mods and texture packs to add/overwrite content
|
||||||
|
|
||||||
IResource handbookFile = null;
|
IResource handbookFile = null;
|
||||||
|
List<IResource> handbookFiles = new ArrayList<>();
|
||||||
|
|
||||||
try{
|
try{
|
||||||
handbookFile = manager.getResource(new ResourceLocation(Wizardry.MODID, "texts/handbook_"
|
handbookFile = manager.getResource(new ResourceLocation(Wizardry.MODID, "texts/handbook_"
|
||||||
+ Minecraft.getMinecraft().getLanguageManager().getCurrentLanguage().getLanguageCode() + ".json"));
|
+ Minecraft.getMinecraft().getLanguageManager().getCurrentLanguage().getLanguageCode() + ".json"));
|
||||||
}catch(IOException e){
|
}catch(Exception e){
|
||||||
|
|
||||||
Wizardry.logger.info("Wizard handbook JSON file missing for the current language (" + Minecraft.getMinecraft()
|
Wizardry.logger.info("Wizard handbook JSON file missing for the current language (" + Minecraft.getMinecraft()
|
||||||
.getLanguageManager().getCurrentLanguage() + "). Using default (English-US) instead.");
|
.getLanguageManager().getCurrentLanguage() + "). Using default (English-US) instead.");
|
||||||
@@ -476,7 +487,29 @@ public class GuiWizardHandbook extends GuiScreen {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return handbookFile;
|
handbookFiles.add(handbookFile);
|
||||||
|
|
||||||
|
for (String modid : ADDONS) {
|
||||||
|
// Addons
|
||||||
|
Wizardry.logger.info("Registering addon Wizard's Handbook contents for " + modid);
|
||||||
|
try{
|
||||||
|
handbookFile = manager.getResource(new ResourceLocation(modid, "texts/handbook_"
|
||||||
|
+ Minecraft.getMinecraft().getLanguageManager().getCurrentLanguage().getLanguageCode() + ".json"));
|
||||||
|
}catch(Exception e){
|
||||||
|
|
||||||
|
Wizardry.logger.info("Wizard handbook JSON file missing for the current language (" + Minecraft.getMinecraft()
|
||||||
|
.getLanguageManager().getCurrentLanguage() + "). Using default (English-US) instead.");
|
||||||
|
|
||||||
|
try{
|
||||||
|
handbookFile = manager.getResource(new ResourceLocation(modid, "texts/handbook_en_us.json"));
|
||||||
|
}catch(IOException x){
|
||||||
|
Wizardry.logger.error("Couldn't find file: " + DEFAULT + ". The file may be missing; please try re-downloading and reinstalling Wizardry.", x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handbookFiles.add(handbookFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return handbookFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Controls
|
// Controls
|
||||||
@@ -576,4 +609,9 @@ public class GuiWizardHandbook extends GuiScreen {
|
|||||||
sections.values().forEach(s -> s.updateUnlockStatus(showToasts, completedAdvancements));
|
sections.values().forEach(s -> s.updateUnlockStatus(showToasts, completedAdvancements));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void registerAddonHandbookContent(String modid) {
|
||||||
|
if (!ADDONS.contains(modid)) {
|
||||||
|
ADDONS.add(modid);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -299,7 +299,7 @@ class Section {
|
|||||||
String suffix = "";
|
String suffix = "";
|
||||||
|
|
||||||
// Account for trailing punctuation, except in languages that don't use spaces such as Chinese
|
// 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());
|
boolean spaceless = SPACELESS_LANGUAGES.contains(Minecraft.getMinecraft().getLanguageManager().getCurrentLanguage() == null ? "en_us" : Minecraft.getMinecraft().getLanguageManager().getCurrentLanguage().getLanguageCode());
|
||||||
if(!spaceless) paragraph.substring(linkEnd).split("\\s", 2)[0].substring(1); // substring(1) to remove the @
|
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
|
// The index of the single page currently being formatted, relative to the section
|
||||||
|
|||||||
@@ -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;
|
package electroblob.wizardry.constants;
|
||||||
|
|
||||||
|
import electroblob.wizardry.Wizardry;
|
||||||
import electroblob.wizardry.WizardryEventHandler;
|
import electroblob.wizardry.WizardryEventHandler;
|
||||||
|
|
||||||
/** Stores various global constants used in Wizardry. */
|
/** 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. */
|
/** The bonus amount of wand upgrades that can be applied to a non-elemental wand. */
|
||||||
public static final int NON_ELEMENTAL_UPGRADE_BONUS = 3;
|
public static final int NON_ELEMENTAL_UPGRADE_BONUS = 3;
|
||||||
/** The fraction by which cooldowns are reduced for each level of cooldown upgrade. */
|
/** 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. */
|
/** The fraction by which maximum charge is increased for each level of storage upgrade. */
|
||||||
public static final float STORAGE_INCREASE_PER_LEVEL = 0.15f;
|
public static final float STORAGE_INCREASE_PER_LEVEL = 0.15f;
|
||||||
/** The fraction by which potency is increased for each tier of matching wand. */
|
/** 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. */
|
/** 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. */
|
/** 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. */
|
/** 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. */
|
/** The fraction by which movement speed is reduced per level of frost effect. */
|
||||||
public static final double FROST_SLOWNESS_PER_LEVEL = 0.5;
|
public static final double FROST_SLOWNESS_PER_LEVEL = 0.5;
|
||||||
/** The fraction by which movement speed is reduced per level of decay effect. */
|
/** 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.
|
* won't spawn again if something is already standing in it.
|
||||||
*/
|
*/
|
||||||
public static final int DECAY_SPREAD_INTERVAL = 8;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,11 @@ public interface IStoredVariable<T> extends IVariable<T> {
|
|||||||
this.ticker = (p, t) -> t; // Initialise this with a do-nothing function, can be overwritten later
|
this.ticker = (p, t) -> t; // Initialise this with a do-nothing function, can be overwritten later
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces this variable's update method with the given update function. <i>Beware of auto-unboxing of
|
* Replaces this variable's update method with the given update function. <i>Beware of auto-unboxing of
|
||||||
* primitive types! For lambda expressions, check the second parameter isn't null before operating on it.
|
* primitive types! For lambda expressions, check the second parameter isn't null before operating on it.
|
||||||
|
|||||||
@@ -47,7 +47,10 @@ public interface IVariable<T> {
|
|||||||
*/
|
*/
|
||||||
void write(ByteBuf buf, T value);
|
void write(ByteBuf buf, T value);
|
||||||
|
|
||||||
|
String getKey();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
*
|
||||||
* Reads this variable's value from the given {@link ByteBuf}.
|
* Reads this variable's value from the given {@link ByteBuf}.
|
||||||
*/
|
*/
|
||||||
T read(ByteBuf buf);
|
T read(ByteBuf buf);
|
||||||
@@ -110,6 +113,11 @@ public interface IVariable<T> {
|
|||||||
// NYI
|
// NYI
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getKey() {
|
||||||
|
return "none"; // we don't mind as these are never synced (electroblob.wizardry.data.IVariable.Variable.isSynced)
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T read(ByteBuf buf){
|
public T read(ByteBuf buf){
|
||||||
return null; // NYI
|
return null; // NYI
|
||||||
|
|||||||
@@ -199,9 +199,14 @@ public class WizardData implements INBTSerializable<NBTTagCompound> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a set containing the registered {@link IStoredVariable} objects for which {@link IVariable#isSynced()}
|
/** Returns a set containing the registered {@link IStoredVariable} objects for which {@link IVariable#isSynced()}
|
||||||
* returns true. Used internally for packet reading. */
|
* returns true, ordered by their keys obtained from {@link IVariable#getKey()}. Used internally for packets. */
|
||||||
public static Set<IVariable> getSyncedVariables(){
|
public static Set<IVariable> getSyncedVariablesOrderedByKey(){
|
||||||
return storedVariables.stream().filter(IVariable::isSynced).collect(Collectors.toSet());
|
Comparator<IVariable> keyComparator = Comparator.comparing(IVariable::getKey);
|
||||||
|
|
||||||
|
return storedVariables.stream()
|
||||||
|
.filter(IVariable::isSynced)
|
||||||
|
.sorted(keyComparator)
|
||||||
|
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -382,6 +387,7 @@ public class WizardData implements INBTSerializable<NBTTagCompound> {
|
|||||||
activeImbuements.add((Imbuement)enchantment);
|
activeImbuements.add((Imbuement)enchantment);
|
||||||
}else{
|
}else{
|
||||||
// Otherwise, removes the enchantment from the item
|
// Otherwise, removes the enchantment from the item
|
||||||
|
((Imbuement) enchantment).onImbuementRemoval(stack);
|
||||||
iterator.remove(); // FIXME: Apparently this can cause a CME
|
iterator.remove(); // FIXME: Apparently this can cause a CME
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package electroblob.wizardry.entity.construct;
|
package electroblob.wizardry.entity.construct;
|
||||||
|
|
||||||
|
import electroblob.wizardry.entity.projectile.EntityConjuredArrow;
|
||||||
import electroblob.wizardry.registry.Spells;
|
import electroblob.wizardry.registry.Spells;
|
||||||
import electroblob.wizardry.spell.Spell;
|
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.util.math.MathHelper;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
@@ -30,7 +28,7 @@ public class EntityArrowRain extends EntityScaledConstruct {
|
|||||||
double y = posY + world.rand.nextDouble() * (double)height;
|
double y = posY + world.rand.nextDouble() * (double)height;
|
||||||
double z = posZ + (world.rand.nextDouble() - 0.5D) * (double)width;
|
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.motionX = MathHelper.cos((float)Math.toRadians(this.rotationYaw + 90));
|
||||||
arrow.motionY = -0.6;
|
arrow.motionY = -0.6;
|
||||||
@@ -38,7 +36,6 @@ public class EntityArrowRain extends EntityScaledConstruct {
|
|||||||
|
|
||||||
arrow.shootingEntity = this.getCaster();
|
arrow.shootingEntity = this.getCaster();
|
||||||
arrow.setDamage(7.0d * damageMultiplier);
|
arrow.setDamage(7.0d * damageMultiplier);
|
||||||
arrow.setPotionEffect(new ItemStack(Items.ARROW));
|
|
||||||
|
|
||||||
this.world.spawnEntity(arrow);
|
this.world.spawnEntity(arrow);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ public class EntityDecay extends EntityMagicConstruct {
|
|||||||
0.6F + rand.nextFloat() * 0.15F);
|
0.6F + rand.nextFloat() * 0.15F);
|
||||||
|
|
||||||
if(!this.world.isRemote){
|
if(!this.world.isRemote){
|
||||||
List<EntityLivingBase> targets = EntityUtils.getLivingWithinRadius(1.0d, this.posX, this.posY,
|
List<EntityLivingBase> targets = EntityUtils.getLivingWithinCylinder(this.width/2f, this.posX, this.posY,
|
||||||
this.posZ, this.world);
|
this.posZ, this.height, this.world);
|
||||||
for(EntityLivingBase target : targets){
|
for(EntityLivingBase target : targets){
|
||||||
if(target != this.getCaster()){
|
if(target != this.getCaster()){
|
||||||
// If this check wasn't here the potion would be reapplied every tick and hence the entity would be
|
// If this check wasn't here the potion would be reapplied every tick and hence the entity would be
|
||||||
|
|||||||
@@ -32,9 +32,9 @@ public class EntityFireRing extends EntityScaledConstruct {
|
|||||||
|
|
||||||
super.onUpdate();
|
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);
|
List<EntityLivingBase> targets = EntityUtils.getLivingWithinCylinder(this.width/2, this.posX, this.posY, this.posZ, this.height, this.world);
|
||||||
|
|
||||||
for(EntityLivingBase target : targets){
|
for(EntityLivingBase target : targets){
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public class EntityFireSigil extends EntityScaledConstruct {
|
|||||||
|
|
||||||
if(!this.world.isRemote){
|
if(!this.world.isRemote){
|
||||||
|
|
||||||
List<EntityLivingBase> targets = EntityUtils.getLivingWithinRadius(width/2, posX, posY, posZ, world);
|
List<EntityLivingBase> targets = EntityUtils.getLivingWithinCylinder(this.width/2, this.posX, this.posY, this.posZ, this.height, this.world);
|
||||||
|
|
||||||
for(EntityLivingBase target : targets){
|
for(EntityLivingBase target : targets){
|
||||||
|
|
||||||
|
|||||||
@@ -168,6 +168,10 @@ public class EntityForcefield extends EntityMagicConstruct implements ICustomHit
|
|||||||
((EntityPlayerMP)target).connection.sendPacket(new SPacketEntityVelocity(target));
|
((EntityPlayerMP)target).connection.sendPacket(new SPacketEntityVelocity(target));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.ticksExisted % 5 == 0) {
|
||||||
|
this.lifetime = (int) (lifetime * 0.99);
|
||||||
|
}
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
|
|
||||||
Vec3d relativeImpactPos = targetRelativePos.normalize().scale(radius);
|
Vec3d relativeImpactPos = targetRelativePos.normalize().scale(radius);
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ public class EntityFrostSigil extends EntityScaledConstruct {
|
|||||||
|
|
||||||
if(!this.world.isRemote){
|
if(!this.world.isRemote){
|
||||||
|
|
||||||
List<EntityLivingBase> targets = EntityUtils.getLivingWithinRadius(width/2, this.posX, this.posY,
|
List<EntityLivingBase> targets = EntityUtils.getLivingWithinCylinder(width/2, this.posX, this.posY,
|
||||||
this.posZ, this.world);
|
this.posZ, this.height, this.world);
|
||||||
|
|
||||||
for(EntityLivingBase target : targets){
|
for(EntityLivingBase target : targets){
|
||||||
|
|
||||||
|
|||||||
@@ -33,30 +33,32 @@ public class EntityHealAura extends EntityScaledConstruct {
|
|||||||
|
|
||||||
if(!this.world.isRemote){
|
if(!this.world.isRemote){
|
||||||
|
|
||||||
List<EntityLivingBase> targets = EntityUtils.getLivingWithinRadius(width/2, posX, posY, posZ, world);
|
List<EntityLivingBase> targets = EntityUtils.getLivingWithinCylinder(width/2, posX, posY, posZ, this.height, world);
|
||||||
|
|
||||||
for(EntityLivingBase target : targets){
|
for(EntityLivingBase target : targets){
|
||||||
|
|
||||||
if(this.isValidTarget(target)){
|
if(this.isValidTarget(target)){
|
||||||
|
|
||||||
if(target.isEntityUndead()){
|
if(target.isEntityUndead()) {
|
||||||
|
|
||||||
double velX = target.motionX;
|
double velX = target.motionX;
|
||||||
double velY = target.motionY;
|
double velY = target.motionY;
|
||||||
double velZ = target.motionZ;
|
double velZ = target.motionZ;
|
||||||
|
|
||||||
if(this.getCaster() != null){
|
if (this.ticksExisted % 10 == 1) {
|
||||||
target.attackEntityFrom(
|
if (this.getCaster() != null) {
|
||||||
MagicDamage.causeIndirectMagicDamage(this, getCaster(), DamageType.RADIANT),
|
target.attackEntityFrom(
|
||||||
Spells.healing_aura.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier);
|
MagicDamage.causeIndirectMagicDamage(this, getCaster(), DamageType.RADIANT),
|
||||||
}else{
|
Spells.healing_aura.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier);
|
||||||
target.attackEntityFrom(DamageSource.MAGIC, Spells.healing_aura.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier);
|
} else {
|
||||||
}
|
target.attackEntityFrom(DamageSource.MAGIC, Spells.healing_aura.getProperty(Spell.DAMAGE).floatValue() * damageMultiplier);
|
||||||
|
}
|
||||||
|
|
||||||
// Removes knockback
|
// Removes knockback
|
||||||
target.motionX = velX;
|
target.motionX = velX;
|
||||||
target.motionY = velY;
|
target.motionY = velY;
|
||||||
target.motionZ = velZ;
|
target.motionZ = velZ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}else if(target.getHealth() < target.getMaxHealth() && target.ticksExisted % 5 == 0){
|
}else if(target.getHealth() < target.getMaxHealth() && target.ticksExisted % 5 == 0){
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ public class EntityLightningSigil extends EntityScaledConstruct {
|
|||||||
this.setDead();
|
this.setDead();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<EntityLivingBase> targets = EntityUtils.getLivingWithinRadius(width/2, this.posX, this.posY,
|
List<EntityLivingBase> targets = EntityUtils.getLivingWithinCylinder(this.width/2, this.posX, this.posY,
|
||||||
this.posZ, this.world);
|
this.posZ, this.height, this.world);
|
||||||
|
|
||||||
for(EntityLivingBase target : targets){
|
for(EntityLivingBase target : targets){
|
||||||
|
|
||||||
|
|||||||
@@ -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.event.world.BlockEvent;
|
||||||
import net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||||
|
import net.minecraftforge.fml.common.registry.ForgeRegistries;
|
||||||
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
|
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
|
||||||
import net.minecraftforge.fml.relauncher.Side;
|
import net.minecraftforge.fml.relauncher.Side;
|
||||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||||
@@ -67,7 +68,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
|
|||||||
protected Predicate<Entity> targetSelector;
|
protected Predicate<Entity> targetSelector;
|
||||||
|
|
||||||
/** The wizard's trades. */
|
/** The wizard's trades. */
|
||||||
private MerchantRecipeList trades;
|
public MerchantRecipeList trades;
|
||||||
/** The wizard's current customer. */
|
/** The wizard's current customer. */
|
||||||
@Nullable
|
@Nullable
|
||||||
private EntityPlayer customer;
|
private EntityPlayer customer;
|
||||||
@@ -129,8 +130,12 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
|
|||||||
if(entity != null && !entity.isInvisible()
|
if(entity != null && !entity.isInvisible()
|
||||||
&& AllyDesignationSystem.isValidTarget(EntityWizard.this, entity)){
|
&& AllyDesignationSystem.isValidTarget(EntityWizard.this, entity)){
|
||||||
|
|
||||||
// ... and is a mob, a summoned creature ...
|
// ... and is a non summoned creature mob ...
|
||||||
if((entity instanceof IMob || entity instanceof ISummonedCreature
|
if((entity instanceof IMob && !(entity instanceof ISummonedCreature)
|
||||||
|
|
||||||
|
// or is a summoned creature with a mob owner or an owner who has attacked the wizard ...
|
||||||
|
|| entity instanceof ISummonedCreature && (((ISummonedCreature)entity).getOwner() instanceof IMob || ((ISummonedCreature)entity).getOwner() == this.getRevengeTarget() || ((ISummonedCreature) entity).getOwner() == this.getAttackTarget())
|
||||||
|
|
||||||
// ... or in the whitelist ...
|
// ... or in the whitelist ...
|
||||||
|| Arrays.asList(Wizardry.settings.summonedCreatureTargetsWhitelist)
|
|| Arrays.asList(Wizardry.settings.summonedCreatureTargetsWhitelist)
|
||||||
.contains(EntityList.getKey(entity.getClass())))
|
.contains(EntityList.getKey(entity.getClass())))
|
||||||
@@ -637,10 +642,9 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
|
|||||||
if(this.getElement() != Element.MAGIC && rand.nextInt(4) > 0 && !specialismSpells.isEmpty()){
|
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
|
// 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.
|
// wizard has an element.
|
||||||
return new ItemStack(WizardryItems.spell_book, 1,
|
return getBookStackForSpell(specialismSpells.get(rand.nextInt(specialismSpells.size())));
|
||||||
specialismSpells.get(rand.nextInt(specialismSpells.size())).metadata());
|
|
||||||
}else{
|
}else{
|
||||||
return new ItemStack(WizardryItems.spell_book, 1, spells.get(rand.nextInt(spells.size())).metadata());
|
return getBookStackForSpell(spells.get(rand.nextInt(spells.size())));
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
if(this.getElement() != Element.MAGIC && rand.nextInt(4) > 0){
|
if(this.getElement() != Element.MAGIC && rand.nextInt(4) > 0){
|
||||||
@@ -659,10 +663,9 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
|
|||||||
if(this.getElement() != Element.MAGIC && rand.nextInt(4) > 0 && !specialismSpells.isEmpty()){
|
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
|
// 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.
|
// wizard has an element.
|
||||||
return new ItemStack(WizardryItems.spell_book, 1,
|
return getBookStackForSpell(specialismSpells.get(rand.nextInt(specialismSpells.size())));
|
||||||
specialismSpells.get(rand.nextInt(specialismSpells.size())).metadata());
|
|
||||||
}else{
|
}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){
|
}else if(randomiser < 6){
|
||||||
if(this.getElement() != Element.MAGIC && rand.nextInt(4) > 0){
|
if(this.getElement() != Element.MAGIC && rand.nextInt(4) > 0){
|
||||||
@@ -696,10 +699,9 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
|
|||||||
if(this.getElement() != Element.MAGIC && rand.nextInt(4) > 0 && !specialismSpells.isEmpty()){
|
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
|
// 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.
|
// wizard has an element.
|
||||||
return new ItemStack(WizardryItems.spell_book, 1,
|
return getBookStackForSpell(specialismSpells.get(rand.nextInt(specialismSpells.size())));
|
||||||
specialismSpells.get(rand.nextInt(specialismSpells.size())).metadata());
|
|
||||||
}else{
|
}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){
|
}else if(randomiser < 6){
|
||||||
if(this.getElement() != Element.MAGIC && rand.nextInt(4) > 0){
|
if(this.getElement() != Element.MAGIC && rand.nextInt(4) > 0){
|
||||||
@@ -724,8 +726,7 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
|
|||||||
|
|
||||||
if(randomiser < 5 && this.getElement() != Element.MAGIC && !specialismSpells.isEmpty()){
|
if(randomiser < 5 && this.getElement() != Element.MAGIC && !specialismSpells.isEmpty()){
|
||||||
// Master spells can only be sold by a specialist in that element.
|
// Master spells can only be sold by a specialist in that element.
|
||||||
return new ItemStack(WizardryItems.spell_book, 1,
|
return getBookStackForSpell(specialismSpells.get(rand.nextInt(specialismSpells.size())));
|
||||||
specialismSpells.get(rand.nextInt(specialismSpells.size())).metadata());
|
|
||||||
|
|
||||||
}else if(randomiser < 6){
|
}else if(randomiser < 6){
|
||||||
if(this.getElement() != Element.MAGIC && rand.nextInt(4) > 0){
|
if(this.getElement() != Element.MAGIC && rand.nextInt(4) > 0){
|
||||||
@@ -801,7 +802,6 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
|
|||||||
Tier maxTier = Tier.NOVICE;
|
Tier maxTier = Tier.NOVICE;
|
||||||
|
|
||||||
List<Spell> npcSpells = Spell.getSpells(s -> s.canBeCastBy(wizard, false));
|
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++){
|
for(int i = 0; i < n; i++){
|
||||||
|
|
||||||
@@ -849,6 +849,22 @@ public class EntityWizard extends EntityCreature implements INpc, IMerchant, ISp
|
|||||||
return maxTier;
|
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
|
@Override
|
||||||
public void writeSpawnData(ByteBuf data){
|
public void writeSpawnData(ByteBuf data){
|
||||||
data.writeInt(textureIndex);
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ArtefactCheckEvent 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -31,19 +31,19 @@ import net.minecraftforge.fml.common.eventhandler.Event;
|
|||||||
public class ImbuementActivateEvent extends Event {
|
public class ImbuementActivateEvent extends Event {
|
||||||
|
|
||||||
/** The item stack being imbued */
|
/** The item stack being imbued */
|
||||||
ItemStack input;
|
public ItemStack input;
|
||||||
|
|
||||||
/** The elements of the four receptacles */
|
/** The elements of the four receptacles */
|
||||||
Element[] receptacleElements;
|
public Element[] receptacleElements;
|
||||||
|
|
||||||
/** A reference to the current world object (may be null if {@code fullLootGen} is false) */
|
/** A reference to the current world object (may be null if {@code fullLootGen} is false) */
|
||||||
World world;
|
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) */
|
/** 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) */
|
||||||
EntityPlayer lastUser;
|
public EntityPlayer lastUser;
|
||||||
|
|
||||||
/** The resulting item stack of the imbuement process */
|
/** The resulting item stack of the imbuement process */
|
||||||
ItemStack result;
|
public ItemStack result;
|
||||||
|
|
||||||
public ImbuementActivateEvent(ItemStack input, Element[] receptacleElements, World world, EntityPlayer lastUser, ItemStack result) {
|
public ImbuementActivateEvent(ItemStack input, Element[] receptacleElements, World world, EntityPlayer lastUser, ItemStack result) {
|
||||||
super();
|
super();
|
||||||
|
|||||||
@@ -46,6 +46,10 @@ public final class WizardryBaublesIntegration {
|
|||||||
ARTEFACT_TYPE_MAP.put(ItemArtefact.Type.RING, BaubleType.RING);
|
ARTEFACT_TYPE_MAP.put(ItemArtefact.Type.RING, BaubleType.RING);
|
||||||
ARTEFACT_TYPE_MAP.put(ItemArtefact.Type.AMULET, BaubleType.AMULET);
|
ARTEFACT_TYPE_MAP.put(ItemArtefact.Type.AMULET, BaubleType.AMULET);
|
||||||
ARTEFACT_TYPE_MAP.put(ItemArtefact.Type.CHARM, BaubleType.CHARM);
|
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(){
|
public static boolean enabled(){
|
||||||
|
|||||||
@@ -452,6 +452,24 @@ public class ContainerArcaneWorkbench extends Container implements ISpellSortabl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called (via {@link electroblob.wizardry.packet.PacketControlInput PacketControlInput}) when the clear button in
|
||||||
|
* the arcane workbench GUI is pressed.
|
||||||
|
*/
|
||||||
|
// As of 2.1, for the sake of events and neatness of code, this was moved here from TileEntityArcaneWorkbench.
|
||||||
|
// As of 4.2, the spell binding/charging/upgrading code was delegated (via IWorkbenchItem) to the items themselves.
|
||||||
|
public void onClearButtonPressed(EntityPlayer player){
|
||||||
|
|
||||||
|
Slot centre = this.getSlot(CENTRE_SLOT);
|
||||||
|
|
||||||
|
if(centre.getStack().getItem() instanceof IWorkbenchItem){ // Should always be true, but no harm in checking.
|
||||||
|
|
||||||
|
Slot[] spellBooks = this.inventorySlots.subList(0, 8).toArray(new Slot[8]);
|
||||||
|
|
||||||
|
((IWorkbenchItem) centre.getStack().getItem()).onClearButtonPressed(player, centre, this.getSlot(CRYSTAL_SLOT), this.getSlot(UPGRADE_SLOT), spellBooks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Scrolls to the given row number. */
|
/** Scrolls to the given row number. */
|
||||||
public void scrollTo(int row){
|
public void scrollTo(int row){
|
||||||
this.scroll = row;
|
this.scroll = row;
|
||||||
|
|||||||
@@ -55,6 +55,26 @@ public interface IWorkbenchItem {
|
|||||||
*/
|
*/
|
||||||
boolean onApplyButtonPressed(EntityPlayer player, Slot centre, Slot crystals, Slot upgrade, Slot[] spellBooks);
|
boolean onApplyButtonPressed(EntityPlayer player, Slot centre, Slot crystals, Slot upgrade, Slot[] spellBooks);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when this item is in the central slot of an arcane workbench and the apply clear is pressed. Items must
|
||||||
|
* implement this method to define what happens when the apply button is pressed.
|
||||||
|
* @param player The player that pressed the apply button.
|
||||||
|
* @param centre The central slot in the arcane workbench. This slot will always contain a stack of the implementing
|
||||||
|
* item, or in other words, <i>it is guaranteed that</i> {@code this == centre.getStack().getItem()}.
|
||||||
|
* @param crystals The magic crystal slot of the arcane workbench.
|
||||||
|
* @param upgrade The upgrade slot of the arcane workbench.
|
||||||
|
* @param spellBooks An array of the <i>active</i> (visible) spell book slots in the arcane workbench. The length of
|
||||||
|
* the array will be equal to the value returned by {@link IWorkbenchItem#getSpellSlotCount(ItemStack)}.
|
||||||
|
* */
|
||||||
|
default void onClearButtonPressed(EntityPlayer player, Slot centre, Slot crystals, Slot upgrade, Slot[] spellBooks){};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Must be overridden in the item class to make the clear button in the Arcane Workbench clickable.
|
||||||
|
* */
|
||||||
|
default boolean isClearable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the tooltip (dark grey box) should be drawn when this item is in an arcane workbench. Only
|
* Returns whether the tooltip (dark grey box) should be drawn when this item is in an arcane workbench. Only
|
||||||
* called client-side.
|
* called client-side.
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import electroblob.wizardry.entity.living.ISummonedCreature;
|
|||||||
import electroblob.wizardry.entity.projectile.EntityDart;
|
import electroblob.wizardry.entity.projectile.EntityDart;
|
||||||
import electroblob.wizardry.entity.projectile.EntityForceOrb;
|
import electroblob.wizardry.entity.projectile.EntityForceOrb;
|
||||||
import electroblob.wizardry.entity.projectile.EntityIceShard;
|
import electroblob.wizardry.entity.projectile.EntityIceShard;
|
||||||
|
import electroblob.wizardry.event.ArtefactCheckEvent;
|
||||||
import electroblob.wizardry.event.SpellCastEvent;
|
import electroblob.wizardry.event.SpellCastEvent;
|
||||||
import electroblob.wizardry.event.SpellCastEvent.Source;
|
import electroblob.wizardry.event.SpellCastEvent.Source;
|
||||||
import electroblob.wizardry.integration.DamageSafetyChecker;
|
import electroblob.wizardry.integration.DamageSafetyChecker;
|
||||||
@@ -37,6 +38,7 @@ import net.minecraft.util.text.TextFormatting;
|
|||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraft.world.biome.Biome;
|
import net.minecraft.world.biome.Biome;
|
||||||
import net.minecraftforge.common.BiomeDictionary;
|
import net.minecraftforge.common.BiomeDictionary;
|
||||||
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
import net.minecraftforge.common.capabilities.ICapabilityProvider;
|
import net.minecraftforge.common.capabilities.ICapabilityProvider;
|
||||||
import net.minecraftforge.event.entity.living.LivingDeathEvent;
|
import net.minecraftforge.event.entity.living.LivingDeathEvent;
|
||||||
import net.minecraftforge.event.entity.living.LivingEvent;
|
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 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 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;
|
public final int maxAtOnce;
|
||||||
|
|
||||||
@@ -178,6 +184,13 @@ public class ItemArtefact extends Item {
|
|||||||
|
|
||||||
if(!((ItemArtefact)artefact).enabled) return false; // Disabled in the config
|
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()){
|
if(WizardryBaublesIntegration.enabled()){
|
||||||
return WizardryBaublesIntegration.isBaubleEquipped(player, artefact);
|
return WizardryBaublesIntegration.isBaubleEquipped(player, artefact);
|
||||||
}else{
|
}else{
|
||||||
@@ -769,6 +782,7 @@ public class ItemArtefact extends Item {
|
|||||||
&& Streams.stream(player.getHeldEquipment()).anyMatch(s -> s.getItem() instanceof ISpellCastingItem
|
&& Streams.stream(player.getHeldEquipment()).anyMatch(s -> s.getItem() instanceof ISpellCastingItem
|
||||||
&& ((ISpellCastingItem)s.getItem()).getCurrentSpell(s).getElement() == Element.NECROMANCY))){
|
&& ((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());
|
CurseOfSoulbinding.getSoulboundCreatures(WizardData.get(player)).add(event.getEntity().getUniqueID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -193,14 +193,6 @@ public class ItemFlamecatcher extends ItemBow implements IConjuredItem {
|
|||||||
charge = net.minecraftforge.event.ForgeEventFactory.onArrowLoose(stack, world, (EntityPlayer)entity, charge, true);
|
charge = net.minecraftforge.event.ForgeEventFactory.onArrowLoose(stack, world, (EntityPlayer)entity, charge, true);
|
||||||
if(charge < 0) return;
|
if(charge < 0) return;
|
||||||
|
|
||||||
if(stack.getTagCompound() != null){
|
|
||||||
int shotsLeft = stack.getTagCompound().getInteger(Flamecatcher.SHOTS_REMAINING_NBT_KEY) - 1;
|
|
||||||
stack.getTagCompound().setInteger(Flamecatcher.SHOTS_REMAINING_NBT_KEY, shotsLeft);
|
|
||||||
if(shotsLeft == 0 && !world.isRemote){
|
|
||||||
stack.setItemDamage(getMaxDamage(stack) - getAnimationFrames());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float velocity = (float)charge / DRAW_TIME;
|
float velocity = (float)charge / DRAW_TIME;
|
||||||
velocity = (velocity * velocity + velocity * 2) / 3;
|
velocity = (velocity * velocity + velocity * 2) / 3;
|
||||||
|
|
||||||
@@ -208,6 +200,14 @@ public class ItemFlamecatcher extends ItemBow implements IConjuredItem {
|
|||||||
|
|
||||||
if((double)velocity >= 0.1D){
|
if((double)velocity >= 0.1D){
|
||||||
|
|
||||||
|
if(stack.getTagCompound() != null){
|
||||||
|
int shotsLeft = stack.getTagCompound().getInteger(Flamecatcher.SHOTS_REMAINING_NBT_KEY) - 1;
|
||||||
|
stack.getTagCompound().setInteger(Flamecatcher.SHOTS_REMAINING_NBT_KEY, shotsLeft);
|
||||||
|
if(shotsLeft == 0 && !world.isRemote){
|
||||||
|
stack.setItemDamage(getMaxDamage(stack) - getAnimationFrames());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(!world.isRemote){
|
if(!world.isRemote){
|
||||||
EntityFlamecatcherArrow arrow = new EntityFlamecatcherArrow(world);
|
EntityFlamecatcherArrow arrow = new EntityFlamecatcherArrow(world);
|
||||||
arrow.aim(player, EntityFlamecatcherArrow.SPEED * velocity);
|
arrow.aim(player, EntityFlamecatcherArrow.SPEED * velocity);
|
||||||
|
|||||||
@@ -244,7 +244,7 @@ public class ItemScroll extends Item implements ISpellCastingItem, IWorkbenchIte
|
|||||||
MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Finish(Source.SCROLL, spell, user, modifiers, castingTick));
|
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);
|
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());
|
((EntityPlayer)user).getCooldownTracker().setCooldown(this, spell.getCooldown());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package electroblob.wizardry.item;
|
package electroblob.wizardry.item;
|
||||||
|
|
||||||
import electroblob.wizardry.Wizardry;
|
import electroblob.wizardry.Wizardry;
|
||||||
|
import electroblob.wizardry.entity.projectile.EntityConjuredArrow;
|
||||||
import electroblob.wizardry.registry.Spells;
|
import electroblob.wizardry.registry.Spells;
|
||||||
import electroblob.wizardry.util.InventoryUtils;
|
import electroblob.wizardry.util.InventoryUtils;
|
||||||
import net.minecraft.enchantment.EnchantmentHelper;
|
import net.minecraft.enchantment.EnchantmentHelper;
|
||||||
@@ -14,6 +15,7 @@ import net.minecraft.init.SoundEvents;
|
|||||||
import net.minecraft.item.IItemPropertyGetter;
|
import net.minecraft.item.IItemPropertyGetter;
|
||||||
import net.minecraft.item.ItemArrow;
|
import net.minecraft.item.ItemArrow;
|
||||||
import net.minecraft.item.ItemBow;
|
import net.minecraft.item.ItemBow;
|
||||||
|
import net.minecraft.item.ItemSpectralArrow;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.stats.StatList;
|
import net.minecraft.stats.StatList;
|
||||||
import net.minecraft.util.*;
|
import net.minecraft.util.*;
|
||||||
@@ -197,8 +199,7 @@ public class ItemSpectralBow extends ItemBow implements IConjuredItem {
|
|||||||
|
|
||||||
if(!world.isRemote){
|
if(!world.isRemote){
|
||||||
|
|
||||||
ItemArrow itemarrow = (ItemArrow)Items.ARROW;
|
EntityConjuredArrow entityarrow = new EntityConjuredArrow(world, entityplayer);
|
||||||
EntityArrow entityarrow = itemarrow.createArrow(world, new ItemStack(itemarrow), entityplayer);
|
|
||||||
entityarrow.shoot(entityplayer, entityplayer.rotationPitch, entityplayer.rotationYaw, 0.0F,
|
entityarrow.shoot(entityplayer, entityplayer.rotationPitch, entityplayer.rotationYaw, 0.0F,
|
||||||
f * 3.0F, 1.0F);
|
f * 3.0F, 1.0F);
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import net.minecraft.inventory.Slot;
|
|||||||
import net.minecraft.item.EnumAction;
|
import net.minecraft.item.EnumAction;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
import net.minecraft.util.*;
|
import net.minecraft.util.*;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.RayTraceResult;
|
import net.minecraft.util.math.RayTraceResult;
|
||||||
@@ -45,6 +46,7 @@ import net.minecraftforge.fml.relauncher.Side;
|
|||||||
import net.minecraftforge.fml.relauncher.SideOnly;
|
import net.minecraftforge.fml.relauncher.SideOnly;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
@@ -226,9 +228,15 @@ public class ItemWand extends Item implements IWorkbenchItem, ISpellCastingItem,
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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
|
// 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){
|
if(!world.isRemote && !this.isManaFull(stack) && world.getTotalWorldTime() % Constants.CONDENSER_TICK_INTERVAL == 0){
|
||||||
@@ -836,8 +844,19 @@ public class ItemWand extends Item implements IWorkbenchItem, ISpellCastingItem,
|
|||||||
Spell spell = Spell.byMetadata(spellBooks[i].getStack().getItemDamage());
|
Spell spell = Spell.byMetadata(spellBooks[i].getStack().getItemDamage());
|
||||||
// If the wand is powerful enough for the spell, it's not already bound to that slot and it's enabled for wands
|
// If the wand is powerful enough for the spell, it's not already bound to that slot and it's enabled for wands
|
||||||
if(!(spell.getTier().level > this.tier.level) && spells[i] != spell && spell.isEnabled(SpellProperties.Context.WANDS)){
|
if(!(spell.getTier().level > this.tier.level) && spells[i] != spell && spell.isEnabled(SpellProperties.Context.WANDS)){
|
||||||
|
|
||||||
|
// Decide if we can bind this multiple times
|
||||||
|
if (Wizardry.settings.preventBindingSameSpellTwiceToWands && Arrays.stream(spells).anyMatch(s -> s == spell)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
spells[i] = spell;
|
spells[i] = spell;
|
||||||
changed = true;
|
changed = true;
|
||||||
|
|
||||||
|
// setting to consume books upon use
|
||||||
|
if (Wizardry.settings.singleUseSpellBooks) {
|
||||||
|
spellBooks[i].getStack().shrink(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -845,31 +864,35 @@ public class ItemWand extends Item implements IWorkbenchItem, ISpellCastingItem,
|
|||||||
WandHelper.setSpells(centre.getStack(), spells);
|
WandHelper.setSpells(centre.getStack(), spells);
|
||||||
|
|
||||||
// Charges wand by appropriate amount
|
// Charges wand by appropriate amount
|
||||||
if(crystals.getStack() != ItemStack.EMPTY && !this.isManaFull(centre.getStack())){
|
if (WandHelper.rechargeManaOnApplyButtonPressed(centre, crystals)) {
|
||||||
|
|
||||||
int chargeDepleted = this.getManaCapacity(centre.getStack()) - this.getMana(centre.getStack());
|
|
||||||
|
|
||||||
int manaPerItem = Constants.MANA_PER_CRYSTAL;
|
|
||||||
if(crystals.getStack().getItem() == WizardryItems.crystal_shard) manaPerItem = Constants.MANA_PER_SHARD;
|
|
||||||
if(crystals.getStack().getItem() == WizardryItems.grand_crystal) manaPerItem = Constants.GRAND_CRYSTAL_MANA;
|
|
||||||
|
|
||||||
if(crystals.getStack().getCount() * manaPerItem < chargeDepleted){
|
|
||||||
// If there aren't enough crystals to fully charge the wand
|
|
||||||
this.rechargeMana(centre.getStack(), crystals.getStack().getCount() * manaPerItem);
|
|
||||||
crystals.decrStackSize(crystals.getStack().getCount());
|
|
||||||
|
|
||||||
}else{
|
|
||||||
// If there are excess crystals (or just enough)
|
|
||||||
this.setMana(centre.getStack(), this.getManaCapacity(centre.getStack()));
|
|
||||||
crystals.decrStackSize((int)Math.ceil(((double)chargeDepleted) / manaPerItem));
|
|
||||||
}
|
|
||||||
|
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClearButtonPressed(EntityPlayer player, Slot centre, Slot crystals, Slot upgrade, Slot[] spellBooks){
|
||||||
|
ItemStack stack = centre.getStack();
|
||||||
|
if (stack.hasTagCompound() && stack.getTagCompound().hasKey(WandHelper.SPELL_ARRAY_KEY)) {
|
||||||
|
NBTTagCompound nbt = stack.getTagCompound();
|
||||||
|
int[] spells = nbt.getIntArray(WandHelper.SPELL_ARRAY_KEY);
|
||||||
|
int expectedSlotCount = BASE_SPELL_SLOTS + WandHelper.getUpgradeLevel(stack,
|
||||||
|
WizardryItems.attunement_upgrade);
|
||||||
|
|
||||||
|
// unbrick broken wands
|
||||||
|
if (spells.length < expectedSlotCount) {
|
||||||
|
spells = new int[expectedSlotCount];
|
||||||
|
}
|
||||||
|
Arrays.fill(spells, 0);
|
||||||
|
nbt.setIntArray(WandHelper.SPELL_ARRAY_KEY, spells);
|
||||||
|
stack.setTagCompound(nbt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isClearable() { return true; }
|
||||||
|
|
||||||
// hitEntity is only called server-side, so we'll have to use events
|
// hitEntity is only called server-side, so we'll have to use events
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onAttackEntityEvent(AttackEntityEvent event){
|
public static void onAttackEntityEvent(AttackEntityEvent event){
|
||||||
|
|||||||
@@ -209,8 +209,8 @@ public class ItemWizardArmour extends ItemArmor implements IWorkbenchItem, IMana
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onArmorTick(World world, EntityPlayer player, ItemStack itemStack){
|
public void onArmorTick(World world, EntityPlayer player, ItemStack itemStack){
|
||||||
if(armorType == EntityEquipmentSlot.HEAD && isWearingFullSet(player, element, ArmourClass.BATTLEMAGE)
|
if(armorType == EntityEquipmentSlot.HEAD && player.ticksExisted % 20 == 0
|
||||||
&& player.ticksExisted % 20 == 0){
|
&& isWearingFullSet(player, element, ArmourClass.BATTLEMAGE) && doAllArmourPiecesHaveMana(player)){
|
||||||
player.addPotionEffect(new PotionEffect(WizardryPotions.ward, 219, 0, true, false));
|
player.addPotionEffect(new PotionEffect(WizardryPotions.ward, 219, 0, true, false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -237,7 +237,7 @@ public class ItemWizardArmour extends ItemArmor implements IWorkbenchItem, IMana
|
|||||||
modifiers.set(WizardryItems.cooldown_upgrade, modifiers.get(WizardryItems.cooldown_upgrade) - armourClass.cooldownReduction, true);
|
modifiers.set(WizardryItems.cooldown_upgrade, modifiers.get(WizardryItems.cooldown_upgrade) - armourClass.cooldownReduction, true);
|
||||||
|
|
||||||
// Full set bonuses
|
// 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){
|
if(armourClass == ArmourClass.SAGE && spell.getElement() != this.element){
|
||||||
modifiers.set(SpellModifiers.COST, 1 - SAGE_OTHER_COST_REDUCTION, false);
|
modifiers.set(SpellModifiers.COST, 1 - SAGE_OTHER_COST_REDUCTION, false);
|
||||||
}
|
}
|
||||||
@@ -334,7 +334,12 @@ public class ItemWizardArmour extends ItemArmor implements IWorkbenchItem, IMana
|
|||||||
|
|
||||||
int chargeDepleted = this.getManaCapacity(centre.getStack()) - this.getMana(centre.getStack());
|
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.crystal_shard) manaPerItem = Constants.MANA_PER_SHARD;
|
||||||
if(crystals.getStack().getItem() == WizardryItems.grand_crystal) manaPerItem = Constants.GRAND_CRYSTAL_MANA;
|
if(crystals.getStack().getItem() == WizardryItems.grand_crystal) manaPerItem = Constants.GRAND_CRYSTAL_MANA;
|
||||||
|
|
||||||
@@ -363,7 +368,7 @@ public class ItemWizardArmour extends ItemArmor implements IWorkbenchItem, IMana
|
|||||||
|
|
||||||
IAttributeInstance movementSpeed = event.getEntityLiving().getAttributeMap().getAttributeInstance(SharedMonsterAttributes.MOVEMENT_SPEED);
|
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)
|
// 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){
|
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));
|
movementSpeed.applyModifier(new AttributeModifier(WARLOCK_SPEED_BOOST_UUID, "Warlock set bonus", WARLOCK_SPEED_BOOST, Operations.MULTIPLY_FLAT));
|
||||||
@@ -433,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.
|
* @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.
|
* @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);
|
ItemStack helmet = entity.getItemStackFromSlot(EntityEquipmentSlot.HEAD);
|
||||||
if(!(helmet.getItem() instanceof ItemWizardArmour)) return false;
|
if(!(helmet.getItem() instanceof ItemWizardArmour)) return false;
|
||||||
Element e = element == null ? ((ItemWizardArmour)helmet.getItem()).element : element;
|
Element e = element == null ? ((ItemWizardArmour)helmet.getItem()).element : element;
|
||||||
@@ -444,6 +449,16 @@ public class ItemWizardArmour extends ItemArmor implements IWorkbenchItem, IMana
|
|||||||
&& ((ItemWizardArmour)entity.getItemStackFromSlot(s).getItem()).armourClass == ac);
|
&& ((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
|
@SubscribeEvent
|
||||||
public static void onLivingSetAttackTargetEvent(LivingSetAttackTargetEvent event){
|
public static void onLivingSetAttackTargetEvent(LivingSetAttackTargetEvent event){
|
||||||
// Undo the mob detection penalty for wearing armour when invisible
|
// 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.EnumActionResult;
|
||||||
import net.minecraft.util.EnumHand;
|
import net.minecraft.util.EnumHand;
|
||||||
import net.minecraft.util.text.Style;
|
import net.minecraft.util.text.Style;
|
||||||
|
import net.minecraft.util.text.TextComponentTranslation;
|
||||||
import net.minecraft.util.text.TextFormatting;
|
import net.minecraft.util.text.TextFormatting;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
@@ -36,7 +37,11 @@ public class ItemWizardHandbook extends Item {
|
|||||||
@Override
|
@Override
|
||||||
public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand){
|
public ActionResult<ItemStack> onItemRightClick(World world, EntityPlayer player, EnumHand hand){
|
||||||
ItemStack stack = player.getHeldItem(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);
|
return ActionResult.newResult(EnumActionResult.SUCCESS, stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -486,6 +486,8 @@ public abstract class Forfeit {
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
add(Tier.MASTER, Element.SORCERY, create("teleport_self_large_distance", (w, p) -> ((Banish)Spells.banish).teleport(p, w, 8 + w.rand.nextDouble() * 700)));
|
||||||
|
|
||||||
add(Tier.NOVICE, Element.HEALING, create("damage_self", (w, p) -> p.attackEntityFrom(DamageSource.MAGIC, 4)));
|
add(Tier.NOVICE, Element.HEALING, create("damage_self", (w, p) -> p.attackEntityFrom(DamageSource.MAGIC, 4)));
|
||||||
|
|
||||||
add(Tier.NOVICE, Element.HEALING, create("spill_armour", (w, p) -> {
|
add(Tier.NOVICE, Element.HEALING, create("spill_armour", (w, p) -> {
|
||||||
|
|||||||
@@ -51,6 +51,17 @@ public class PacketControlInput implements IMessageHandler<Message, IMessage> {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CLEAR_BUTTON:
|
||||||
|
|
||||||
|
if(!(player.openContainer instanceof ContainerArcaneWorkbench)){
|
||||||
|
Wizardry.logger.warn("Received a PacketControlInput, but the player that sent it was not " +
|
||||||
|
"currently using an arcane workbench. This should not happen!");
|
||||||
|
}else{
|
||||||
|
((ContainerArcaneWorkbench)player.openContainer).onClearButtonPressed(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
case NEXT_SPELL_KEY:
|
case NEXT_SPELL_KEY:
|
||||||
|
|
||||||
if(wand.getItem() instanceof ISpellCastingItem){
|
if(wand.getItem() instanceof ISpellCastingItem){
|
||||||
@@ -133,7 +144,7 @@ public class PacketControlInput implements IMessageHandler<Message, IMessage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public enum ControlType {
|
public enum ControlType {
|
||||||
APPLY_BUTTON, NEXT_SPELL_KEY, PREVIOUS_SPELL_KEY, RESURRECT_BUTTON, CANCEL_RESURRECT, POSSESSION_PROJECTILE
|
APPLY_BUTTON, NEXT_SPELL_KEY, PREVIOUS_SPELL_KEY, RESURRECT_BUTTON, CANCEL_RESURRECT, POSSESSION_PROJECTILE, CLEAR_BUTTON
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Message implements IMessage {
|
public static class Message implements IMessage {
|
||||||
|
|||||||
@@ -10,7 +10,11 @@ import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
|
|||||||
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
|
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
|
||||||
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
|
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <b>[Server -> Client]</b> This packet is sent to synchronise any fields that need synchronising in
|
* <b>[Server -> Client]</b> This packet is sent to synchronise any fields that need synchronising in
|
||||||
@@ -54,9 +58,8 @@ public class PacketPlayerSync implements IMessageHandler<Message, IMessage> {
|
|||||||
|
|
||||||
this.seed = buf.readLong();
|
this.seed = buf.readLong();
|
||||||
this.selectedMinionID = buf.readInt();
|
this.selectedMinionID = buf.readInt();
|
||||||
|
|
||||||
this.spellData = new HashMap<>();
|
this.spellData = new HashMap<>();
|
||||||
WizardData.getSyncedVariables().forEach(v -> spellData.put(v, v.read(buf)));
|
WizardData.getSyncedVariablesOrderedByKey().forEach(v -> spellData.put(v, v.read(buf)));
|
||||||
// Have to send empty tags to guarantee correct ByteBuf size/order, but no point keeping the resulting nulls
|
// Have to send empty tags to guarantee correct ByteBuf size/order, but no point keeping the resulting nulls
|
||||||
spellData.values().removeIf(Objects::isNull);
|
spellData.values().removeIf(Objects::isNull);
|
||||||
|
|
||||||
@@ -73,7 +76,7 @@ public class PacketPlayerSync implements IMessageHandler<Message, IMessage> {
|
|||||||
buf.writeLong(seed);
|
buf.writeLong(seed);
|
||||||
buf.writeInt(selectedMinionID);
|
buf.writeInt(selectedMinionID);
|
||||||
|
|
||||||
WizardData.getSyncedVariables().forEach(v -> v.write(buf, spellData.get(v)));
|
WizardData.getSyncedVariablesOrderedByKey().forEach(v -> v.write(buf, spellData.get(v)));
|
||||||
|
|
||||||
if(this.spellsDiscovered == null) return;
|
if(this.spellsDiscovered == null) return;
|
||||||
for(Spell spell : this.spellsDiscovered){
|
for(Spell spell : this.spellsDiscovered){
|
||||||
|
|||||||
@@ -20,9 +20,7 @@ public class PacketSpellProperties implements IMessageHandler<PacketSpellPropert
|
|||||||
if(ctx.side.isClient()){
|
if(ctx.side.isClient()){
|
||||||
|
|
||||||
net.minecraft.client.Minecraft.getMinecraft().addScheduledTask(() -> {
|
net.minecraft.client.Minecraft.getMinecraft().addScheduledTask(() -> {
|
||||||
|
for(int i=0; i<message.propertiesArray.length; i++){
|
||||||
int first = message.firstId;
|
|
||||||
for(int i = first; i <message.propertiesArray.length; i++){
|
|
||||||
Spell.byNetworkID(i).setPropertiesClient(message.propertiesArray[i]);
|
Spell.byNetworkID(i).setPropertiesClient(message.propertiesArray[i]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -34,24 +32,21 @@ public class PacketSpellProperties implements IMessageHandler<PacketSpellPropert
|
|||||||
public static class Message implements IMessage {
|
public static class Message implements IMessage {
|
||||||
|
|
||||||
private SpellProperties[] propertiesArray;
|
private SpellProperties[] propertiesArray;
|
||||||
private int firstId;
|
|
||||||
private int count;
|
|
||||||
// This constructor is required otherwise you'll get errors (used somewhere in fml through reflection)
|
// This constructor is required otherwise you'll get errors (used somewhere in fml through reflection)
|
||||||
public Message(){}
|
public Message(){}
|
||||||
|
|
||||||
public Message(int firstId, int count, SpellProperties... properties){
|
public Message(SpellProperties... properties){
|
||||||
this.firstId = firstId;
|
|
||||||
this.count = count;
|
|
||||||
this.propertiesArray = properties;
|
this.propertiesArray = properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fromBytes(ByteBuf buf){
|
public void fromBytes(ByteBuf buf){
|
||||||
|
|
||||||
List<SpellProperties> propertiesList = new ArrayList<>();
|
List<SpellProperties> propertiesList = new ArrayList<>();
|
||||||
int i = buf.readInt();
|
int i = 0;
|
||||||
count = buf.readInt();
|
|
||||||
firstId = i;
|
while(buf.isReadable()){
|
||||||
while(buf.isReadable() && i < count){
|
|
||||||
propertiesList.add(new SpellProperties(Spell.byNetworkID(i++), buf));
|
propertiesList.add(new SpellProperties(Spell.byNetworkID(i++), buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,8 +55,6 @@ public class PacketSpellProperties implements IMessageHandler<PacketSpellPropert
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void toBytes(ByteBuf buf){
|
public void toBytes(ByteBuf buf){
|
||||||
buf.writeInt(firstId);
|
|
||||||
buf.writeInt(count);
|
|
||||||
for(SpellProperties properties : propertiesArray) properties.write(buf);
|
for(SpellProperties properties : propertiesArray) properties.write(buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package electroblob.wizardry.potion;
|
package electroblob.wizardry.potion;
|
||||||
|
|
||||||
import electroblob.wizardry.Wizardry;
|
import electroblob.wizardry.Wizardry;
|
||||||
|
import electroblob.wizardry.item.ItemWizardArmour;
|
||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.inventory.EntityEquipmentSlot;
|
import net.minecraft.inventory.EntityEquipmentSlot;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
@@ -45,8 +46,12 @@ public class CurseUndeath extends Curse {
|
|||||||
} else {
|
} else {
|
||||||
itemstack.setItemDamage(itemstack.getItemDamage() + entitylivingbase.world.rand.nextInt(2));
|
itemstack.setItemDamage(itemstack.getItemDamage() + entitylivingbase.world.rand.nextInt(2));
|
||||||
if (itemstack.getItemDamage() >= itemstack.getMaxDamage()) {
|
if (itemstack.getItemDamage() >= itemstack.getMaxDamage()) {
|
||||||
entitylivingbase.renderBrokenItemStack(itemstack);
|
if (itemstack.getItem() instanceof ItemWizardArmour) {
|
||||||
entitylivingbase.setItemStackToSlot(EntityEquipmentSlot.HEAD, ItemStack.EMPTY);
|
entitylivingbase.setFire(8);
|
||||||
|
} else {
|
||||||
|
entitylivingbase.renderBrokenItemStack(itemstack);
|
||||||
|
entitylivingbase.setItemStackToSlot(EntityEquipmentSlot.HEAD, ItemStack.EMPTY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,10 +59,9 @@ public class PotionContainment extends PotionMagicEffect {
|
|||||||
|
|
||||||
if(x != target.posX || y != target.posY || z != target.posZ)
|
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);
|
||||||
if(target.world.isRemote){
|
if(target.world.isRemote){
|
||||||
EntityUtils.undoGravity(target);
|
|
||||||
target.addVelocity(0.15 * Math.signum(x - target.posX), 0.15 * Math.signum(y - target.posY), 0.15 * Math.signum(z - target.posZ));
|
|
||||||
|
|
||||||
target.world.playSound(target.posX, target.posY, target.posZ, WizardrySounds.ENTITY_FORCEFIELD_DEFLECT,
|
target.world.playSound(target.posX, target.posY, target.posZ, WizardrySounds.ENTITY_FORCEFIELD_DEFLECT,
|
||||||
WizardrySounds.SPELLS, 0.3f, 1f, false);
|
WizardrySounds.SPELLS, 0.3f, 1f, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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 GreaterHeal());
|
||||||
registry.register(new SpellConstruct<>("healing_aura", SpellActions.POINT_DOWN, EntityHealAura::new, false).addProperties(Spell.EFFECT_RADIUS, Spell.DAMAGE, Spell.HEALTH));
|
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 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 Transience());
|
||||||
|
|
||||||
registry.register(new Meteor());
|
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 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 SpellConstructRanged<>("black_hole", EntityBlackHole::new, false).addProperties(Spell.EFFECT_RADIUS).soundValues(2, 0.7f, 0));
|
||||||
registry.register(new Shockwave());
|
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 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));
|
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
|
// Wizardry 1.1 spells
|
||||||
@@ -398,7 +399,7 @@ public final class Spells {
|
|||||||
registry.register(new PocketWorkbench());
|
registry.register(new PocketWorkbench());
|
||||||
registry.register(new ImbueWeapon());
|
registry.register(new ImbueWeapon());
|
||||||
registry.register(new InvigoratingPresence());
|
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 SpellProjectile<>("greater_fireball", EntityLargeMagicFireball::new).addProperties(Spell.DAMAGE, EntityLargeMagicFireball.EXPLOSION_POWER));//new GreaterFireball());
|
||||||
registry.register(new FlamingWeapon());
|
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(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(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(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(EntityMagicSlime.class, "magic_slime", TrackingType.LIVING).build());
|
||||||
registry.register(createEntry(EntityDecoy.class, "decoy", 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(EntityDart.class, "dart", TrackingType.PROJECTILE).build());
|
||||||
registry.register(createEntry(EntityIceLance.class, "ice_lance", 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(EntityFlamecatcherArrow.class, "flamecatcher_arrow", TrackingType.PROJECTILE).build());
|
||||||
|
registry.register(createEntry(EntityConjuredArrow.class, "conjured_arrow", TrackingType.PROJECTILE).build());
|
||||||
|
|
||||||
// Directionless projectiles
|
// Directionless projectiles
|
||||||
registry.register(createEntry(EntityFirebomb.class, "firebomb", TrackingType.PROJECTILE).build());
|
registry.register(createEntry(EntityFirebomb.class, "firebomb", TrackingType.PROJECTILE).build());
|
||||||
|
|||||||
@@ -57,6 +57,9 @@ public final class WizardryPotions {
|
|||||||
public static final Potion frost_step = placeholder();
|
public static final Potion frost_step = placeholder();
|
||||||
public static final Potion mark_of_sacrifice = placeholder();
|
public static final Potion mark_of_sacrifice = placeholder();
|
||||||
public static final Potion mirage = 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
|
* 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
|
public void spawnCustomParticle(World world, double x, double y, double z){} // We only want the syncing
|
||||||
}.setBeneficial());
|
}.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());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,7 @@ import electroblob.wizardry.constants.Constants;
|
|||||||
import electroblob.wizardry.entity.living.ISpellCaster;
|
import electroblob.wizardry.entity.living.ISpellCaster;
|
||||||
import electroblob.wizardry.event.SpellCastEvent;
|
import electroblob.wizardry.event.SpellCastEvent;
|
||||||
import electroblob.wizardry.item.SpellActions;
|
import electroblob.wizardry.item.SpellActions;
|
||||||
|
import electroblob.wizardry.registry.Spells;
|
||||||
import electroblob.wizardry.registry.WizardryItems;
|
import electroblob.wizardry.registry.WizardryItems;
|
||||||
import electroblob.wizardry.registry.WizardryPotions;
|
import electroblob.wizardry.registry.WizardryPotions;
|
||||||
import electroblob.wizardry.util.ParticleBuilder;
|
import electroblob.wizardry.util.ParticleBuilder;
|
||||||
@@ -24,11 +25,14 @@ import javax.annotation.Nullable;
|
|||||||
@Mod.EventBusSubscriber
|
@Mod.EventBusSubscriber
|
||||||
public class EmpoweringPresence extends SpellAreaEffect {
|
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(){
|
public EmpoweringPresence(){
|
||||||
super("empowering_presence", SpellActions.POINT_UP, false);
|
super("empowering_presence", SpellActions.POINT_UP, false);
|
||||||
this.alwaysSucceed(true);
|
this.alwaysSucceed(true);
|
||||||
this.targetAllies(true);
|
this.targetAllies(true);
|
||||||
addProperties(EFFECT_DURATION, EFFECT_STRENGTH);
|
addProperties(EFFECT_DURATION, EFFECT_STRENGTH, POTENCY_PER_LEVEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -62,7 +66,7 @@ public class EmpoweringPresence extends SpellAreaEffect {
|
|||||||
if(event.getCaster() != null && event.getCaster().isPotionActive(WizardryPotions.empowerment)
|
if(event.getCaster() != null && event.getCaster().isPotionActive(WizardryPotions.empowerment)
|
||||||
&& !(event.getSpell() instanceof EmpoweringPresence)){ // Prevent exponential empowerment stacking!
|
&& !(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.getCaster().getActivePotionEffect(WizardryPotions.empowerment).getAmplifier() + 1);
|
||||||
|
|
||||||
event.getModifiers().set(SpellModifiers.POTENCY,
|
event.getModifiers().set(SpellModifiers.POTENCY,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import electroblob.wizardry.item.SpellActions;
|
|||||||
import electroblob.wizardry.util.ParticleBuilder;
|
import electroblob.wizardry.util.ParticleBuilder;
|
||||||
import electroblob.wizardry.util.ParticleBuilder.Type;
|
import electroblob.wizardry.util.ParticleBuilder.Type;
|
||||||
import electroblob.wizardry.util.SpellModifiers;
|
import electroblob.wizardry.util.SpellModifiers;
|
||||||
import net.minecraft.entity.EntityCreature;
|
import net.minecraft.entity.EntityLiving;
|
||||||
import net.minecraft.entity.EntityLivingBase;
|
import net.minecraft.entity.EntityLivingBase;
|
||||||
import net.minecraft.tileentity.TileEntityDispenser;
|
import net.minecraft.tileentity.TileEntityDispenser;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
@@ -29,7 +29,7 @@ public class Enrage extends SpellAreaEffect {
|
|||||||
@Override
|
@Override
|
||||||
protected boolean affectEntity(World world, Vec3d origin, @Nullable EntityLivingBase caster, EntityLivingBase target, int targetCount, int ticksInUse, SpellModifiers modifiers){
|
protected boolean affectEntity(World world, Vec3d origin, @Nullable EntityLivingBase caster, EntityLivingBase target, int targetCount, int ticksInUse, SpellModifiers modifiers){
|
||||||
|
|
||||||
if(caster != null && target instanceof EntityCreature){
|
if(caster != null && target instanceof EntityLiving){
|
||||||
target.setRevengeTarget(caster); // Yours truly, angry mobs
|
target.setRevengeTarget(caster); // Yours truly, angry mobs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public class FireBreath extends SpellRay {
|
|||||||
this.getNameForTranslationFormatted()), true);
|
this.getNameForTranslationFormatted()), true);
|
||||||
// This now only damages in line with the maxHurtResistantTime. Some mods don't play nicely and fiddle
|
// 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.
|
// 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 if(ticksInUse % 10 == 0){
|
||||||
target.setFire((int)(getProperty(BURN_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)));
|
target.setFire((int)(getProperty(BURN_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)));
|
||||||
EntityUtils.attackEntityWithoutKnockback(target,
|
EntityUtils.attackEntityWithoutKnockback(target,
|
||||||
MagicDamage.causeDirectMagicDamage(caster, DamageType.FIRE),
|
MagicDamage.causeDirectMagicDamage(caster, DamageType.FIRE),
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ public class FlameRay extends SpellRay {
|
|||||||
this.getNameForTranslationFormatted()), true);
|
this.getNameForTranslationFormatted()), true);
|
||||||
// This now only damages in line with the maxHurtResistantTime. Some mods don't play nicely and fiddle
|
// 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.
|
// 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 if(ticksInUse % 10 == 0){
|
||||||
target.setFire((int)(getProperty(BURN_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)));
|
target.setFire((int)(getProperty(BURN_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)));
|
||||||
EntityUtils.attackEntityWithoutKnockback(target,
|
EntityUtils.attackEntityWithoutKnockback(target,
|
||||||
MagicDamage.causeDirectMagicDamage(caster, DamageType.FIRE),
|
MagicDamage.causeDirectMagicDamage(caster, DamageType.FIRE),
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public class FrostRay extends SpellRay {
|
|||||||
(int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)),
|
(int)(getProperty(EFFECT_DURATION).floatValue() * modifiers.get(WizardryItems.duration_upgrade)),
|
||||||
getProperty(EFFECT_STRENGTH).intValue()));
|
getProperty(EFFECT_STRENGTH).intValue()));
|
||||||
|
|
||||||
if(ticksInUse % ((EntityLivingBase)target).maxHurtResistantTime == 1){
|
if(ticksInUse % 10 == 0){
|
||||||
float damage = getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY);
|
float damage = getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY);
|
||||||
if(target instanceof EntityBlaze || target instanceof EntityMagmaCube) damage *= 2;
|
if(target instanceof EntityBlaze || target instanceof EntityMagmaCube) damage *= 2;
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public class Heal extends SpellBuff {
|
|||||||
entity.heal(health);
|
entity.heal(health);
|
||||||
|
|
||||||
// If the player is able to heal, they can't possibly have absorption hearts, so no need to check!
|
// If the player is able to heal, they can't possibly have absorption hearts, so no need to check!
|
||||||
if(excessHealth > 0 && entity instanceof EntityPlayer
|
if(excessHealth > entity.getAbsorptionAmount() && entity instanceof EntityPlayer
|
||||||
&& ItemArtefact.isArtefactActive((EntityPlayer)entity, WizardryItems.amulet_absorption)){
|
&& ItemArtefact.isArtefactActive((EntityPlayer)entity, WizardryItems.amulet_absorption)){
|
||||||
entity.setAbsorptionAmount(excessHealth);
|
entity.setAbsorptionAmount(excessHealth);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class LifeDrain extends SpellRay {
|
|||||||
|
|
||||||
if(EntityUtils.isLiving(target)){
|
if(EntityUtils.isLiving(target)){
|
||||||
|
|
||||||
if(ticksInUse % 12 == 0){
|
if(ticksInUse % 10 == 0){
|
||||||
|
|
||||||
float damage = getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY);
|
float damage = getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY);
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ public class LightningRay extends SpellRay {
|
|||||||
this.getNameForTranslationFormatted()), true);
|
this.getNameForTranslationFormatted()), true);
|
||||||
// This now only damages in line with the maxHurtResistantTime. Some mods don't play nicely and fiddle
|
// 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.
|
// 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 if(ticksInUse % 10 == 0){
|
||||||
EntityUtils.attackEntityWithoutKnockback(target,
|
EntityUtils.attackEntityWithoutKnockback(target,
|
||||||
MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK),
|
MagicDamage.causeDirectMagicDamage(caster, DamageType.SHOCK),
|
||||||
getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY));
|
getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY));
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public class LightningWeb extends SpellRay {
|
|||||||
@Override
|
@Override
|
||||||
protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){
|
protected boolean onEntityHit(World world, Entity target, Vec3d hit, EntityLivingBase caster, Vec3d origin, int ticksInUse, SpellModifiers modifiers){
|
||||||
|
|
||||||
if(EntityUtils.isLiving(target)){
|
if(EntityUtils.isLiving(target) && ticksInUse % 10 == 0){
|
||||||
|
|
||||||
electrocute(world, caster, origin, target, getProperty(PRIMARY_DAMAGE).floatValue()
|
electrocute(world, caster, origin, target, getProperty(PRIMARY_DAMAGE).floatValue()
|
||||||
* modifiers.get(SpellModifiers.POTENCY), ticksInUse);
|
* modifiers.get(SpellModifiers.POTENCY), ticksInUse);
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public class MarkSacrifice extends SpellRay {
|
|||||||
PotionEffect effect = event.getEntityLiving().getActivePotionEffect(WizardryPotions.mark_of_sacrifice);
|
PotionEffect effect = event.getEntityLiving().getActivePotionEffect(WizardryPotions.mark_of_sacrifice);
|
||||||
|
|
||||||
if(effect != null && event.getSource().isMagicDamage()){
|
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);
|
event.getEntityLiving().removePotionEffect(WizardryPotions.mark_of_sacrifice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,9 +30,14 @@ public class Paralysis extends SpellRay {
|
|||||||
* will end. */
|
* will end. */
|
||||||
private static final String CRITICAL_HEALTH = "critical_health";
|
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(){
|
public Paralysis(){
|
||||||
super("paralysis", SpellActions.POINT, false);
|
super("paralysis", SpellActions.POINT, false);
|
||||||
addProperties(DAMAGE, EFFECT_DURATION, CRITICAL_HEALTH);
|
addProperties(DAMAGE, EFFECT_DURATION, CRITICAL_HEALTH, PLAYER_EFFECT_DURATION_MULTIPLIER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -58,8 +63,9 @@ public class Paralysis extends SpellRay {
|
|||||||
getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY));
|
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,
|
((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;
|
return false;
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ public class RayOfPurification extends SpellRay {
|
|||||||
if(!world.isRemote && ticksInUse == 1 && caster instanceof EntityPlayer) ((EntityPlayer)caster)
|
if(!world.isRemote && ticksInUse == 1 && caster instanceof EntityPlayer) ((EntityPlayer)caster)
|
||||||
.sendStatusMessage(new TextComponentTranslation("spell.resist", target.getName(),
|
.sendStatusMessage(new TextComponentTranslation("spell.resist", target.getName(),
|
||||||
this.getNameForTranslationFormatted()), true);
|
this.getNameForTranslationFormatted()), true);
|
||||||
}else{
|
}else if (ticksInUse % 10 == 0) {
|
||||||
|
|
||||||
float damage = getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY);
|
float damage = getProperty(DAMAGE).floatValue() * modifiers.get(SpellModifiers.POTENCY);
|
||||||
// Fire
|
// Fire
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
|
|||||||
private static int nextSpellId = 0;
|
private static int nextSpellId = 0;
|
||||||
/** The spell's integer ID, mainly used for networking. */
|
/** The spell's integer ID, mainly used for networking. */
|
||||||
// This was added after I learnt the hard way why you can't assume Forge's registry IDs are sequential...
|
// This was added after I learnt the hard way why you can't assume Forge's registry IDs are sequential...
|
||||||
private final int id;
|
private int id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This constructor should be called from any subclasses, either feeding in the constants directly or through their
|
* 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.icon = new ResourceLocation(modID, "textures/spells/" + name + ".png");
|
||||||
this.sounds = createSounds();
|
this.sounds = createSounds();
|
||||||
this.id = nextSpellId++;
|
this.id = nextSpellId++;
|
||||||
|
Wizardry.logger.debug("Registering spell " + this.unlocalisedName +" with networkID " + id);
|
||||||
this.items(WizardryItems.spell_book, WizardryItems.scroll);
|
this.items(WizardryItems.spell_book, WizardryItems.scroll);
|
||||||
this.npcSelector((e, o) -> false);
|
this.npcSelector((e, o) -> false);
|
||||||
}
|
}
|
||||||
@@ -319,24 +320,8 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
|
|||||||
// To avoid sending extra data unnecessarily, the spell properties are sent in order of spell ID
|
// To avoid sending extra data unnecessarily, the spell properties are sent in order of spell ID
|
||||||
List<Spell> spells = new ArrayList<>(registry.getValuesCollection());
|
List<Spell> spells = new ArrayList<>(registry.getValuesCollection());
|
||||||
spells.sort(Comparator.comparingInt(Spell::networkID));
|
spells.sort(Comparator.comparingInt(Spell::networkID));
|
||||||
|
WizardryPacketHandler.net.sendTo(new PacketSpellProperties.Message(spells.stream()
|
||||||
SpellProperties[] propertiesArray = spells.stream().map(s -> s.properties).toArray(SpellProperties[]::new);
|
.map(s -> s.properties).toArray(SpellProperties[]::new)), player);
|
||||||
|
|
||||||
// splitting the packet into batches of 100 spells
|
|
||||||
int i = 0;
|
|
||||||
while (i < propertiesArray.length) {
|
|
||||||
List<SpellProperties> propertiesList = new ArrayList<>();
|
|
||||||
int first = i;
|
|
||||||
int batchCounter = 0;
|
|
||||||
for (int currentIndex = i; currentIndex < propertiesArray.length && batchCounter < 100; currentIndex++) {
|
|
||||||
propertiesList.add(propertiesArray[currentIndex]);
|
|
||||||
batchCounter++;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
SpellProperties[] currentArray = propertiesList.toArray(new SpellProperties[0]);
|
|
||||||
PacketSpellProperties.Message currentPacket = new PacketSpellProperties.Message(first, currentArray.length, currentArray);
|
|
||||||
WizardryPacketHandler.net.sendTo(currentPacket, player);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void clearProperties(){
|
private static void clearProperties(){
|
||||||
@@ -576,6 +561,11 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
|
|||||||
return id;
|
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. */
|
/** Returns the {@code ResourceLocation} for this spell's icon. */
|
||||||
public final ResourceLocation getIcon(){
|
public final ResourceLocation getIcon(){
|
||||||
return icon;
|
return icon;
|
||||||
@@ -932,6 +922,11 @@ public abstract class Spell extends IForgeRegistryEntry.Impl<Spell> implements C
|
|||||||
return Arrays.asList(applicableItems).contains(item);
|
return Arrays.asList(applicableItems).contains(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns the list of items this spell is applicable to. */
|
||||||
|
public List<Item> getApplicableItems() {
|
||||||
|
return Arrays.asList(applicableItems);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets which items this spell can appear on (these default to the regular spell book and scroll).
|
* Sets which items this spell can appear on (these default to the regular spell book and scroll).
|
||||||
* @param applicableItems The items this spell should naturally appear on (or no items at all).
|
* @param applicableItems The items this spell should naturally appear on (or no items at all).
|
||||||
|
|||||||
@@ -125,7 +125,8 @@ public class SpellBuff extends Spell {
|
|||||||
@Override
|
@Override
|
||||||
public boolean cast(World world, EntityLiving caster, EnumHand hand, int ticksInUse, EntityLivingBase target, SpellModifiers modifiers){
|
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.
|
// 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
|
// Only return on the server side or the client probably won't spawn particles
|
||||||
if(!this.applyEffects(caster, modifiers) && !world.isRemote) return false;
|
if(!this.applyEffects(caster, modifiers) && !world.isRemote) return false;
|
||||||
if(world.isRemote) this.spawnParticles(world, caster, modifiers);
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
package electroblob.wizardry.spell;
|
package electroblob.wizardry.spell;
|
||||||
|
|
||||||
import electroblob.wizardry.Wizardry;
|
import electroblob.wizardry.Wizardry;
|
||||||
|
import electroblob.wizardry.item.ItemArtefact;
|
||||||
import electroblob.wizardry.item.SpellActions;
|
import electroblob.wizardry.item.SpellActions;
|
||||||
|
import electroblob.wizardry.registry.WizardryItems;
|
||||||
import electroblob.wizardry.util.SpellModifiers;
|
import electroblob.wizardry.util.SpellModifiers;
|
||||||
import net.minecraft.block.state.IBlockState;
|
import net.minecraft.block.state.IBlockState;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
@@ -34,7 +36,7 @@ public class Telekinesis extends SpellRay {
|
|||||||
target.motionZ = (origin.z - target.posZ) / 6;
|
target.motionZ = (origin.z - target.posZ) / 6;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}else if(target instanceof EntityPlayer && (Wizardry.settings.telekineticDisarmament || !(caster instanceof EntityPlayer))){
|
} else if (target instanceof EntityPlayer && (Wizardry.settings.telekineticDisarmament && !ItemArtefact.isArtefactActive((EntityPlayer) target, WizardryItems.amulet_anchoring)) {
|
||||||
|
|
||||||
EntityPlayer player = (EntityPlayer)target;
|
EntityPlayer player = (EntityPlayer)target;
|
||||||
|
|
||||||
|
|||||||
@@ -141,6 +141,11 @@ public final class AllyDesignationSystem {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tests whether the target is a creature that was summoned/tamed (or is otherwise owned) by the attacker
|
||||||
|
if(target instanceof IEntityOwnable && attacker instanceof EntityLiving && !(((EntityLiving)attacker).getRevengeTarget() == ((IEntityOwnable)target).getOwner() || ((EntityLiving)attacker).getAttackTarget() == ((IEntityOwnable)target).getOwner())){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Tests whether the target is a creature that was mind controlled by the attacker
|
// Tests whether the target is a creature that was mind controlled by the attacker
|
||||||
if(target instanceof EntityLiving && ((EntityLivingBase)target).isPotionActive(WizardryPotions.mind_control)){
|
if(target instanceof EntityLiving && ((EntityLivingBase)target).isPotionActive(WizardryPotions.mind_control)){
|
||||||
|
|
||||||
@@ -201,7 +206,7 @@ public final class AllyDesignationSystem {
|
|||||||
// Owned entities inherit their owner's allies
|
// Owned entities inherit their owner's allies
|
||||||
if(allyOf instanceof IEntityOwnable){
|
if(allyOf instanceof IEntityOwnable){
|
||||||
Entity owner = ((IEntityOwnable)allyOf).getOwner();
|
Entity owner = ((IEntityOwnable)allyOf).getOwner();
|
||||||
if(owner instanceof EntityLivingBase && isAllied((EntityLivingBase)owner, possibleAlly)) return true;
|
if(owner instanceof EntityLivingBase && (owner == possibleAlly || isAllied((EntityLivingBase)owner, possibleAlly))) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(allyOf instanceof EntityPlayer && possibleAlly instanceof EntityPlayer
|
if(allyOf instanceof EntityPlayer && possibleAlly instanceof EntityPlayer
|
||||||
|
|||||||
@@ -117,6 +117,45 @@ public final class EntityUtils {
|
|||||||
return entityList;
|
return entityList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all EntityLivingBase within the cylinder radius of the given coordinates. This should
|
||||||
|
* used by circle effects.
|
||||||
|
*
|
||||||
|
* @param radius The search radius
|
||||||
|
* @param x The x coordinate to search around
|
||||||
|
* @param y The y coordinate to search around
|
||||||
|
* @param z The z coordinate to search around
|
||||||
|
* @param height The height of the cylinder
|
||||||
|
* @param world The world to search in
|
||||||
|
*/
|
||||||
|
public static List<EntityLivingBase> getLivingWithinCylinder(double radius, double x, double y, double z, double height, World world) {
|
||||||
|
return getEntitiesWithinCylinder(radius, x, y, z, height, world, EntityLivingBase.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all entities of the specified type within the cylinder radius of the given coordinates. This should
|
||||||
|
* used by circle effects.
|
||||||
|
*
|
||||||
|
* @param radius The search radius
|
||||||
|
* @param x The x coordinate to search around
|
||||||
|
* @param y The y coordinate to search around
|
||||||
|
* @param z The z coordinate to search around
|
||||||
|
* @param height The height of the cylinder
|
||||||
|
* @param world The world to search in
|
||||||
|
* @param entityType The class of entity to search for; pass in Entity.class for all entities
|
||||||
|
*/
|
||||||
|
public static <T extends Entity> List<T> getEntitiesWithinCylinder(double radius, double x, double y, double z, double height, World world, Class<T> entityType) {
|
||||||
|
AxisAlignedBB aabb = new AxisAlignedBB(x - radius, y, z - radius, x + radius, y + height, z + radius);
|
||||||
|
List<T> entityList = world.getEntitiesWithinAABB(entityType, aabb);
|
||||||
|
for(T entity : entityList) {
|
||||||
|
if (entity.getDistance(x, entity.posY, z) > radius) {
|
||||||
|
entityList.remove(entity);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return entityList;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an entity from its UUID. If the UUID is known to belong to an {@code EntityPlayer}, use the more efficient
|
* Gets an entity from its UUID. If the UUID is known to belong to an {@code EntityPlayer}, use the more efficient
|
||||||
* {@link World#getPlayerEntityByUUID(UUID)} instead.
|
* {@link World#getPlayerEntityByUUID(UUID)} instead.
|
||||||
|
|||||||
@@ -20,8 +20,7 @@ public interface ISpellSortable {
|
|||||||
|
|
||||||
TIER("tier", Comparator.naturalOrder()),
|
TIER("tier", Comparator.naturalOrder()),
|
||||||
ELEMENT("element", Comparator.comparing(Spell::getElement).thenComparing(Spell::getTier)),
|
ELEMENT("element", Comparator.comparing(Spell::getElement).thenComparing(Spell::getTier)),
|
||||||
ALPHABETICAL("alphabetical", Comparator.comparing(Spell::getUnlocalisedName));
|
ALPHABETICAL("alphabetical", Comparator.comparing(s -> s.getRegistryName().getPath().toString()));
|
||||||
|
|
||||||
public String name;
|
public String name;
|
||||||
public Comparator<? super Spell> comparator;
|
public Comparator<? super Spell> comparator;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package electroblob.wizardry.util;
|
package electroblob.wizardry.util;
|
||||||
|
|
||||||
|
import electroblob.wizardry.Settings;
|
||||||
|
import electroblob.wizardry.Wizardry;
|
||||||
import electroblob.wizardry.entity.living.*;
|
import electroblob.wizardry.entity.living.*;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.boss.EntityDragon;
|
import net.minecraft.entity.boss.EntityDragon;
|
||||||
@@ -195,7 +197,7 @@ public class MagicDamage extends EntityDamageSource implements IElementalDamage
|
|||||||
* @return A damagesource object of type EntityDamageSource
|
* @return A damagesource object of type EntityDamageSource
|
||||||
*/
|
*/
|
||||||
public static DamageSource causeDirectMagicDamage(Entity caster, DamageType type, boolean isRetaliatory){
|
public static DamageSource causeDirectMagicDamage(Entity caster, DamageType type, boolean isRetaliatory){
|
||||||
return new MagicDamage(DIRECT_MAGIC_DAMAGE, caster, type, isRetaliatory);
|
return new MagicDamage(getDirectDamageNameForType(type), caster, type, isRetaliatory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -241,7 +243,15 @@ public class MagicDamage extends EntityDamageSource implements IElementalDamage
|
|||||||
*/
|
*/
|
||||||
public static DamageSource causeIndirectMagicDamage(Entity magic, Entity caster, DamageType type,
|
public static DamageSource causeIndirectMagicDamage(Entity magic, Entity caster, DamageType type,
|
||||||
boolean isRetaliatory){
|
boolean isRetaliatory){
|
||||||
return new IndirectMagicDamage(INDIRECT_MAGIC_DAMAGE, magic, caster, type, isRetaliatory);
|
return new IndirectMagicDamage(getIndirectDamageNameForType(type), magic, caster, type, isRetaliatory);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getIndirectDamageNameForType(DamageType type) {
|
||||||
|
return Wizardry.settings.damageTypePerElement ? type.name().toLowerCase() + "_" + INDIRECT_MAGIC_DAMAGE : INDIRECT_MAGIC_DAMAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getDirectDamageNameForType(DamageType type) {
|
||||||
|
return Wizardry.settings.damageTypePerElement ? type.name().toLowerCase() + "_" + DIRECT_MAGIC_DAMAGE : DIRECT_MAGIC_DAMAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -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++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,14 @@
|
|||||||
package electroblob.wizardry.util;
|
package electroblob.wizardry.util;
|
||||||
|
|
||||||
|
import electroblob.wizardry.constants.Constants;
|
||||||
|
import electroblob.wizardry.item.IManaStoringItem;
|
||||||
|
import electroblob.wizardry.item.IWorkbenchItem;
|
||||||
|
import electroblob.wizardry.item.ItemCrystal;
|
||||||
import electroblob.wizardry.item.ItemWand;
|
import electroblob.wizardry.item.ItemWand;
|
||||||
import electroblob.wizardry.registry.Spells;
|
import electroblob.wizardry.registry.Spells;
|
||||||
import electroblob.wizardry.registry.WizardryItems;
|
import electroblob.wizardry.registry.WizardryItems;
|
||||||
import electroblob.wizardry.spell.Spell;
|
import electroblob.wizardry.spell.Spell;
|
||||||
|
import net.minecraft.inventory.Slot;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
@@ -494,4 +499,49 @@ public final class WandHelper {
|
|||||||
setProgression(wand, getProgression(wand) + progression);
|
setProgression(wand, getProgression(wand) + progression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recharges the mana of an item when the apply button is pressed in the arcane workbench GUI.
|
||||||
|
* This method requires the central item to implement both the {@link IWorkbenchItem} and {@link IManaStoringItem} interfaces.
|
||||||
|
*
|
||||||
|
* @param centre The slot representing the central item to be recharged.
|
||||||
|
* @param crystals The slot containing mana crystals for recharging.
|
||||||
|
* @return {@code true} if the mana of the central item was successfully recharged, {@code false} otherwise.
|
||||||
|
*/
|
||||||
|
public static boolean rechargeManaOnApplyButtonPressed(Slot centre, Slot crystals) {
|
||||||
|
boolean changed = false;
|
||||||
|
if (!(centre.getStack().getItem() instanceof IWorkbenchItem) || !(centre.getStack().getItem() instanceof IManaStoringItem)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
IManaStoringItem iManaStoringItem = (IManaStoringItem) centre.getStack().getItem();
|
||||||
|
|
||||||
|
// Charges the item by appropriate amount
|
||||||
|
if (crystals.getStack() != ItemStack.EMPTY && !iManaStoringItem.isManaFull(centre.getStack())) {
|
||||||
|
|
||||||
|
int chargeDepleted = iManaStoringItem.getManaCapacity(centre.getStack()) - iManaStoringItem.getMana(centre.getStack());
|
||||||
|
|
||||||
|
// 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;}
|
||||||
|
|
||||||
|
if (crystals.getStack().getCount() * manaPerItem < chargeDepleted) {
|
||||||
|
// If there aren't enough crystals to fully charge the item
|
||||||
|
iManaStoringItem.rechargeMana(centre.getStack(), crystals.getStack().getCount() * manaPerItem);
|
||||||
|
crystals.decrStackSize(crystals.getStack().getCount());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// If there are excess crystals (or just enough)
|
||||||
|
iManaStoringItem.setMana(centre.getStack(), iManaStoringItem.getManaCapacity(centre.getStack()));
|
||||||
|
crystals.decrStackSize((int) Math.ceil(((double) chargeDepleted) / manaPerItem));
|
||||||
|
}
|
||||||
|
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.name=The Wizard's Handbook
|
||||||
item.ebwizardry\:wizard_handbook.author=by %1$s
|
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.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
|
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\: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\: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\: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.name=Ring of Condensing
|
||||||
item.ebwizardry\:ring_condensing.desc=Slowly regenerates mana for all wands on your hotbar
|
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.name=Lokenzen's Ring
|
||||||
item.ebwizardry\:ring_stormcloud.desc=Stormcloud moves towards targets and lasts longer with every strike
|
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.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.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_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
|
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\:decoy.name=Decoy
|
||||||
entity.ebwizardry\:vex_minion.name=Vex
|
entity.ebwizardry\:vex_minion.name=Vex
|
||||||
entity.ebwizardry\:remnant.name=Remnant
|
entity.ebwizardry\:remnant.name=Remnant
|
||||||
|
entity.ebwizardry\:spectral_golem.name=Spectral Golem
|
||||||
|
|
||||||
entity.ebwizardry\:magic_missile.name=Magic
|
entity.ebwizardry\:magic_missile.name=Magic
|
||||||
entity.ebwizardry\:arc.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\:ice_spike.name=Magic
|
||||||
entity.ebwizardry\:combustion_rune.name=Magic
|
entity.ebwizardry\:combustion_rune.name=Magic
|
||||||
entity.ebwizardry\:flamecatcher_arrow.name=Magic
|
entity.ebwizardry\:flamecatcher_arrow.name=Magic
|
||||||
|
entity.ebwizardry\:conjured_arrow.name=Magic
|
||||||
|
|
||||||
entity.ebwizardry\:black_hole.name=Black Hole
|
entity.ebwizardry\:black_hole.name=Black Hole
|
||||||
entity.ebwizardry\:shield.name=Shield
|
entity.ebwizardry\:shield.name=Shield
|
||||||
@@ -875,6 +882,7 @@ container.ebwizardry\:arcane_workbench.sort_tier=Sort by Tier
|
|||||||
container.ebwizardry\:arcane_workbench.sort_element=Sort by Element
|
container.ebwizardry\:arcane_workbench.sort_element=Sort by Element
|
||||||
container.ebwizardry\:arcane_workbench.sort_alphabetical=Sort Alphabetically
|
container.ebwizardry\:arcane_workbench.sort_alphabetical=Sort Alphabetically
|
||||||
container.ebwizardry\:arcane_workbench.search_tooltip=%1$sSearch Tips\n\ntier=%2$s, %1$st=%2$s: match tiers\n%1$selement=%2$s, %1$se=%2$s: match elements\n%1$stype=%2$s, %1$sp=%2$s: match spell types\n%1$sdiscovered=true/false%2$s, %1$sd=t/f%2$s: include only (un)discovered\n%1$smodid=%2$s, %1$sm=%2$s: match mod IDs\n\nSeparate multiple values with %1$s,%2$s\nSeparate multiple criteria with %1$s;
|
container.ebwizardry\:arcane_workbench.search_tooltip=%1$sSearch Tips\n\ntier=%2$s, %1$st=%2$s: match tiers\n%1$selement=%2$s, %1$se=%2$s: match elements\n%1$stype=%2$s, %1$sp=%2$s: match spell types\n%1$sdiscovered=true/false%2$s, %1$sd=t/f%2$s: include only (un)discovered\n%1$smodid=%2$s, %1$sm=%2$s: match mod IDs\n\nSeparate multiple values with %1$s,%2$s\nSeparate multiple criteria with %1$s;
|
||||||
|
container.ebwizardry\:arcane_workbench.clear=Clear Spell Slots
|
||||||
|
|
||||||
container.ebwizardry\:bookshelf=Bookshelf
|
container.ebwizardry\:bookshelf=Bookshelf
|
||||||
|
|
||||||
@@ -1075,7 +1083,7 @@ spell.ebwizardry\:stormcloud=Stormcloud
|
|||||||
spell.ebwizardry\:summon_blaze=Summon Blaze
|
spell.ebwizardry\:summon_blaze=Summon Blaze
|
||||||
spell.ebwizardry\:summon_ice_giant=Summon Ice Giant
|
spell.ebwizardry\:summon_ice_giant=Summon Ice Giant
|
||||||
spell.ebwizardry\:summon_ice_wraith=Summon Ice Wraith
|
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_lightning_wraith=Summon Lightning Wraith
|
||||||
spell.ebwizardry\:summon_phoenix=Summon Phoenix
|
spell.ebwizardry\:summon_phoenix=Summon Phoenix
|
||||||
spell.ebwizardry\:summon_shadow_wraith=Summon Shadow Wraith
|
spell.ebwizardry\:summon_shadow_wraith=Summon Shadow Wraith
|
||||||
@@ -1203,7 +1211,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\: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\:invisibility.desc=Makes the caster invisible for 30 seconds.
|
||||||
spell.ebwizardry\:invoke_weather.desc=Changes the weather in the world.
|
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\: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\: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.
|
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 +1234,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\: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\: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\: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\: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\: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.
|
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.
|
||||||
@@ -1363,6 +1371,7 @@ forfeit.ebwizardry\:bury_self=The ground collapses beneath you!
|
|||||||
|
|
||||||
forfeit.ebwizardry\:spill_inventory=Your items spill themselves everywhere!
|
forfeit.ebwizardry\:spill_inventory=Your items spill themselves everywhere!
|
||||||
forfeit.ebwizardry\:teleport_self=You are instantly teleported somewhere!
|
forfeit.ebwizardry\:teleport_self=You are instantly teleported somewhere!
|
||||||
|
forfeit.ebwizardry\:teleport_self_large_distance=You are instantly teleported somewhere far away!
|
||||||
forfeit.ebwizardry\:levitate_self=You begin to float upwards helplessly!
|
forfeit.ebwizardry\:levitate_self=You begin to float upwards helplessly!
|
||||||
forfeit.ebwizardry\:vex_horde=A horde of vexes materializes around you!
|
forfeit.ebwizardry\:vex_horde=A horde of vexes materializes around you!
|
||||||
forfeit.ebwizardry\:black_hole=A swirling vortex appears in front of you!
|
forfeit.ebwizardry\:black_hole=A swirling vortex appears in front of you!
|
||||||
@@ -1400,6 +1409,9 @@ potion.ebwizardry\:containment=Containment
|
|||||||
potion.ebwizardry\:frost_step=Frost Step
|
potion.ebwizardry\:frost_step=Frost Step
|
||||||
potion.ebwizardry\:mark_of_sacrifice=Mark of Sacrifice
|
potion.ebwizardry\:mark_of_sacrifice=Mark of Sacrifice
|
||||||
potion.ebwizardry\:mirage=Mirage
|
potion.ebwizardry\:mirage=Mirage
|
||||||
|
potion.ebwizardry\:oakflesh=Oakflesh
|
||||||
|
potion.ebwizardry\:ironflesh=Ironflesh
|
||||||
|
potion.ebwizardry\:diamondflesh=Diamondflesh
|
||||||
|
|
||||||
enchantment.ebwizardry\:magic_sword=Imbuement
|
enchantment.ebwizardry\:magic_sword=Imbuement
|
||||||
enchantment.ebwizardry\:magic_bow=Imbuement
|
enchantment.ebwizardry\:magic_bow=Imbuement
|
||||||
@@ -1436,6 +1448,25 @@ key.ebwizardry.spell_8=Spell Slot 8
|
|||||||
|
|
||||||
death.attack.wizardry_magic=%1$s was killed by %2$s using magic
|
death.attack.wizardry_magic=%1$s was killed by %2$s using magic
|
||||||
death.attack.indirect_wizardry_magic=%1$s was killed by %2$s using magic
|
death.attack.indirect_wizardry_magic=%1$s was killed by %2$s using magic
|
||||||
|
death.attack.magic_wizardry_magic=%1$s was killed by %2$s using magic
|
||||||
|
death.attack.magic_indirect_wizardry_magic=%1$s was killed by %2$s using magic
|
||||||
|
|
||||||
|
death.attack.fire_wizardry_magic=%1$s was killed by %2$s using fire magic
|
||||||
|
death.attack.fire_indirect_wizardry_magic=%1$s was killed by %2$s using fire magic
|
||||||
|
death.attack.frost_wizardry_magic=%1$s was killed by %2$s using frost magic
|
||||||
|
death.attack.frost_indirect_wizardry_magic=%1$s was killed by %2$s using frost magic
|
||||||
|
death.attack.shock_wizardry_magic=%1$s was killed by %2$s using a shock magic
|
||||||
|
death.attack.shock_indirect_wizardry_magic=%1$s was killed by %2$s using shock magic
|
||||||
|
death.attack.wither_wizardry_magic=%1$s was killed by %2$s using withering magic
|
||||||
|
death.attack.wither_indirect_wizardry_magic=%1$s was killed by %2$s withering magic
|
||||||
|
death.attack.poison_wizardry_magic=%1$s was killed by %2$s using poison magic
|
||||||
|
death.attack.poison_indirect_wizardry_magic=%1$s was killed by %2$s poison magic
|
||||||
|
death.attack.force_wizardry_magic=%1$s was killed by %2$s using a magical force
|
||||||
|
death.attack.force_indirect_wizardry_magic=%1$s was killed by %2$s using magical force
|
||||||
|
death.attack.blast_wizardry_magic=%1$s was killed by %2$s using a magical blast
|
||||||
|
death.attack.blast_indirect_wizardry_magic=%1$s was killed by %2$s using magical blast
|
||||||
|
death.attack.radiant_wizardry_magic=%1$s was killed by %2$s using radiant magic
|
||||||
|
death.attack.radiant_indirect_wizardry_magic=%1$s was killed by %2$s using radiant magic
|
||||||
|
|
||||||
soundCategory.ebwizardry_spells=Spells
|
soundCategory.ebwizardry_spells=Spells
|
||||||
|
|
||||||
@@ -1504,6 +1535,12 @@ config.ebwizardry.player_block_damage.true=Yes - kaboom!
|
|||||||
config.ebwizardry.player_block_damage.false=No - activate anti-grief (TM)
|
config.ebwizardry.player_block_damage.false=No - activate anti-grief (TM)
|
||||||
config.ebwizardry.dispenser_block_damage=Dispenser Block Damage
|
config.ebwizardry.dispenser_block_damage=Dispenser Block Damage
|
||||||
config.ebwizardry.dispenser_block_damage.tooltip=Whether spells cast by dispensers can destroy blocks in the world. Wizardry makes every attempt to respect protection mods and plugins, but cannot guarantee it will work in all cases for every mod. If you need absolutely watertight anti-grief, disable this setting.
|
config.ebwizardry.dispenser_block_damage.tooltip=Whether spells cast by dispensers can destroy blocks in the world. Wizardry makes every attempt to respect protection mods and plugins, but cannot guarantee it will work in all cases for every mod. If you need absolutely watertight anti-grief, disable this setting.
|
||||||
|
config.ebwizardry.damage_type_per_element=Damage Type Per Element
|
||||||
|
config.ebwizardry.damage_type_per_element.tooltip=Whether damage should be registered with the old system (wizardry_magic/indirect_wizardry_magic) prefixed damage with the elements like necromancy_indirect_wizardry_magic, necromancy_wizardry_magic. This is disabled by default to not break existing modpacks. The intention of this setting is to allow differentiating various damage types for e.g. the Distinct Damage Descriptions mod
|
||||||
|
config.ebwizardry.single_use_spell_books=Spell Books Are Consumed By Wands
|
||||||
|
config.ebwizardry.single_use_spell_books.tooltip=Whether spell books are consumed when they are bound to a wand.
|
||||||
|
config.ebwizardry.prevent_binding_same_spell_twice_to_wands=Prevent Binding The Same Spell To A Wand Multiple Times
|
||||||
|
config.ebwizardry.prevent_binding_same_spell_twice_to_wands.tooltip=Whether to prevent binding the same spell to a wand multiple times
|
||||||
config.ebwizardry.telekinetic_disarmament=Telekinetic Disarmament
|
config.ebwizardry.telekinetic_disarmament=Telekinetic Disarmament
|
||||||
config.ebwizardry.telekinetic_disarmament.tooltip=Whether to allow players to disarm other players using the telekinesis spell. Disable to prevent stealing of items.
|
config.ebwizardry.telekinetic_disarmament.tooltip=Whether to allow players to disarm other players using the telekinesis spell. Disable to prevent stealing of items.
|
||||||
config.ebwizardry.telekinetic_disarmament.true=Yes - let people steal things
|
config.ebwizardry.telekinetic_disarmament.true=Yes - let people steal things
|
||||||
@@ -1524,6 +1561,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.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=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.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=Difficulty Settings
|
||||||
config.ebwizardry.category.difficulty.tooltip=Configure wizardry's difficulty
|
config.ebwizardry.category.difficulty.tooltip=Configure wizardry's difficulty
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -363,6 +363,7 @@
|
|||||||
"spell.zombie_apocalypse.start": {"category": "spells", "sounds": ["ebwizardry:dark_aura_start"]},
|
"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.loop": {"category": "spells", "sounds": ["ebwizardry:dark_aura_loop"]},
|
||||||
"spell.zombie_apocalypse.end": {"category": "spells", "sounds": ["ebwizardry:dark_aura_end"]},
|
"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.burn_self": {"category": "spells", "sounds": ["fire/ignite"]},
|
||||||
"forfeit.fireball": {"category": "spells", "sounds": ["mob/ghast/fireball4"]},
|
"forfeit.fireball": {"category": "spells", "sounds": ["mob/ghast/fireball4"]},
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
"chargeup": 25,
|
"chargeup": 25,
|
||||||
"cooldown": 300,
|
"cooldown": 300,
|
||||||
"base_properties": {
|
"base_properties": {
|
||||||
"resistance_duration": 600,
|
"diamondflesh_duration": 600,
|
||||||
"resistance_strength": 2
|
"diamondflesh_strength": 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -14,11 +14,12 @@
|
|||||||
"element": "healing",
|
"element": "healing",
|
||||||
"type": "buff",
|
"type": "buff",
|
||||||
"cost": 30,
|
"cost": 30,
|
||||||
"chargeup": 0,
|
"chargeup": 20,
|
||||||
"cooldown": 60,
|
"cooldown": 60,
|
||||||
"base_properties": {
|
"base_properties": {
|
||||||
"effect_radius": 5,
|
"effect_radius": 5,
|
||||||
"effect_duration": 900,
|
"effect_duration": 900,
|
||||||
"effect_strength": 1
|
"effect_strength": 0,
|
||||||
|
"potency_per_level": 0.15
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
"chargeup": 15,
|
"chargeup": 15,
|
||||||
"cooldown": 100,
|
"cooldown": 100,
|
||||||
"base_properties": {
|
"base_properties": {
|
||||||
"resistance_duration": 600,
|
"ironflesh_duration": 600,
|
||||||
"resistance_strength": 1
|
"ironflesh_strength": 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
"chargeup": 0,
|
"chargeup": 0,
|
||||||
"cooldown": 50,
|
"cooldown": 50,
|
||||||
"base_properties": {
|
"base_properties": {
|
||||||
"resistance_duration": 600,
|
"oakflesh_duration": 600,
|
||||||
"resistance_strength": 0
|
"oakflesh_strength": 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
"range": 10,
|
"range": 10,
|
||||||
"damage": 4,
|
"damage": 4,
|
||||||
"effect_duration": 100,
|
"effect_duration": 100,
|
||||||
"critical_health": 4
|
"critical_health": 4,
|
||||||
|
"player_effect_duration_multiplier": 0.5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -17,6 +17,8 @@
|
|||||||
"chargeup": 20,
|
"chargeup": 20,
|
||||||
"cooldown": 400,
|
"cooldown": 400,
|
||||||
"base_properties": {
|
"base_properties": {
|
||||||
|
"minion_lifetime": 600,
|
||||||
|
"minion_count": 1,
|
||||||
"summon_radius": 2
|
"summon_radius": 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
"width": 90,
|
"width": 90,
|
||||||
"height": 90
|
"height": 90
|
||||||
},
|
},
|
||||||
"classes": {
|
"classes": {
|
||||||
"location": "ebwizardry:textures/gui/handbook/pictures/classes.png",
|
"location": "ebwizardry:textures/gui/handbook/pictures/classes.png",
|
||||||
"caption": "3가지 분야",
|
"caption": "3가지 분야",
|
||||||
"u": 0,
|
"u": 0,
|
||||||
@@ -89,7 +89,7 @@
|
|||||||
},
|
},
|
||||||
"shrine": {
|
"shrine": {
|
||||||
"location": "ebwizardry:textures/gui/handbook/pictures/shrine.png",
|
"location": "ebwizardry:textures/gui/handbook/pictures/shrine.png",
|
||||||
"caption": "\"자연\"의 신사",
|
"caption": "\"자연\"의 사당",
|
||||||
"u": 0,
|
"u": 0,
|
||||||
"v": 0,
|
"v": 0,
|
||||||
"width": 110,
|
"width": 110,
|
||||||
@@ -296,7 +296,7 @@
|
|||||||
|
|
||||||
"마법사의 안내서",
|
"마법사의 안내서",
|
||||||
|
|
||||||
"Electroblob"
|
"by Electroblob"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -308,7 +308,7 @@
|
|||||||
|
|
||||||
"화살표 모양 버튼을 눌러 쪽을 넘기고, 이중 화살표 모양 버튼을 사용하여 목차 사이를 빠르게 전환할 수 있다네. 목차 목록으로 돌아가려면 중앙 메뉴 버튼을 누르면 된다네.",
|
"화살표 모양 버튼을 눌러 쪽을 넘기고, 이중 화살표 모양 버튼을 사용하여 목차 사이를 빠르게 전환할 수 있다네. 목차 목록으로 돌아가려면 중앙 메뉴 버튼을 누르면 된다네.",
|
||||||
|
|
||||||
"보라색 글씨는 클릭하면 관련 페이지로 바로 이동할 수 있고, 책갈피에 마우스를 대고 마우스 오른쪽 버튼을 클릭하여 현재 페이지를 책갈피로 지정하고, 마우스 왼쪽 버튼을 클릭하여 책갈피가 있는 페이지로 돌아갈 수 있다네."
|
"보라색 글씨는 클릭하면 관련 페이지로 바로 이동할 수 있고, 책갈피에 마우스를 대고 오른쪽 버튼을 클릭하여 현재 페이지를 책갈피로 지정하고, 왼쪽 버튼을 클릭하여 책갈피가 있는 페이지로 돌아갈 수 있다네."
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -333,7 +333,7 @@
|
|||||||
|
|
||||||
"#recipe magic_wand",
|
"#recipe magic_wand",
|
||||||
|
|
||||||
"지팡이를 만들었다면 @arcane_workbench 신비로운 작업대@가 필요하다네. 신비로운 작업대를 제작하는 방법:",
|
"지팡이를 만들었다면 @arcane_workbench 신비로운 작업대@가 필요하다네. 신비로운 작업대를 제작하는 방법:",
|
||||||
|
|
||||||
"#recipe arcane_workbench",
|
"#recipe arcane_workbench",
|
||||||
|
|
||||||
@@ -341,7 +341,7 @@
|
|||||||
|
|
||||||
"#recipe magic_missile_spell_book",
|
"#recipe magic_missile_spell_book",
|
||||||
|
|
||||||
"그리고 마법 수정은 @mana 마나@를 충전하는데 쓰이니 많이 필요할 걸세."
|
"그리고 마법 수정은 @mana 마나@를 충전하는데 쓰이니 많이 필요할 걸세."
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -353,16 +353,16 @@
|
|||||||
],
|
],
|
||||||
"text": [
|
"text": [
|
||||||
|
|
||||||
" 마나는 마법사에게 힘을 주는 불가사의한 에너지다. 마나는 그 자체로 물리적인 물질이 아니라, 세상의 모든 것에 스며드는 항상 존재하는 기운이라네.",
|
" 마나는 마법사에게 힘을 주는 불가사의한 에너지러네. 마나는 그 자체로 물리적인 물질이 아니라, 세상의 모든 것에 스며드는 항상 존재하는 기운이라네.",
|
||||||
"특히 자연적으로 발생하는 결정에서 크게 발현되는데, 지하의 암석에 박혀 있는 것을 발견할 수 있다네.",
|
"특히 자연적으로 발생하는 결정에서 크게 발현되는데, 지하의 암석에 박혀 있는 것을 발견할 수 있다네.",
|
||||||
|
|
||||||
"@wands 지팡이@는 그 안에 마나를 저장하고 사용할 수 있는 장치이고, 이 마나는 @spells 주문@을 사용할 때 마다 사용되며 주문마다 그 위력이나 지속력에 따라 사용하는 마나의 양이 다르다네.",
|
"@wands 지팡이@는 그 안에 마나를 저장하고 사용할 수 있는 장치이고, 이 마나는 @spells 주문@을 사용할 때 마다 사용되며 주문마다 그 위력이나 지속력에 따라 사용하는 마나의 양이 다르다네.",
|
||||||
|
|
||||||
"#image crystal_ore",
|
"#image crystal_ore",
|
||||||
|
|
||||||
"#image magic_crystal",
|
"#image magic_crystal",
|
||||||
" ",
|
" ",
|
||||||
" 마나는 창조되거나 파괴될 수 없으며, 주문을 사용하면 마나가 단순히 주변으로 흩어지게 된다는 것으로 많이 알려져있지만. 사실, 마나는 전세계에 얇게 퍼져있어, 자연적으로 수천 년에 걸쳐 집중되면, 지하에 마법수정이 있는 경우와 마찬가지로, 인공적으로 마나를 창조할 수 있다네. 또한 주문을 사용하여 마나를 사용한 다음 사용된 마나를 회복하는 여러가지 방법들로 마나를 창조할 수 있다네."
|
" 마나는 창조되거나 파괴될 수 없으며, 주문을 사용하면 마나가 단순히 주변으로 흩어지게 된다는 것으로 많이 알려져있지만. 사실, 마나는 전세계에 얇게 퍼져있어, 자연적으로 수천 년에 걸쳐 집중되면, 지하에 마법수정이 있는 경우와 마찬가지로, 인공적으로 마나를 창조할 수 있다네. 또한 주문을 사용하여 마나를 사용한 다음 사용된 마나를 회복하는 여러가지 방법들로 마나를 창조할 수 있다네."
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -374,19 +374,19 @@
|
|||||||
],
|
],
|
||||||
"text": [
|
"text": [
|
||||||
|
|
||||||
"지팡이는 마법사의 무기라네. 지팡이가 감당하는 한에서는 지팡이로는 어떤 @spells 주문@도 사용할 수 있다네 @tiers 등급@ 참조). 지팡이는 다양한 종류가 있지만, 처음 얻는 지팡이는 거의 기본적인 마법 지팡이일 걸세.",
|
"지팡이는 마법사의 무기라네. 지팡이가 감당하는 한에서는 지팡이로는 어떤 @spells 주문@도 사용할 수 있다네 (@tiers 등급@ 참조). 지팡이는 다양한 종류가 있지만, 처음 얻는 지팡이는 거의 기본적인 마법 지팡이일 걸세.",
|
||||||
|
|
||||||
"#image magic_wand",
|
"#image magic_wand",
|
||||||
|
|
||||||
"대부분의 지팡이는 나무 막대기에 마법수정을 연결햐여 만들어졌는고, 반대 쪽 끝에는 금 조각이 부착되어 있다. 물론 수정은 주문을 시전할 때의 필요한 마나를 가지고있기 때문에 지팡이의 힘의 원천이다 그러나 나머지 부분도 중요하다 지팡이를 잡을 수 있는 수단뿐만 아니라 마나가 순환되고 주문을 시전할 수 있는 길을 제공하기 때문이다.",
|
"대부분의 지팡이는 나무 막대기에 마법수정을 연결햐여 만들어졌는고, 반대 쪽 끝에는 금 조각이 부착되어 있다네. 물론 수정은 주문을 시전할 때의 필요한 마나를 가지고있기 때문에 지팡이의 힘의 원천이다만, 나머지 부분도 중요하다 지팡이를 잡을 수 있는 수단뿐만 아니라 마나가 순환되고 주문을 시전할 수 있는 길을 제공하기 때문이라네.",
|
||||||
|
|
||||||
"지팡이로 주문을 많이 사용할 수록 주문시전에 더 효과적이게 되고, 더 높은 등급의 주문을 시전할 수 있다네. 지팡이 자체의 모양과 모양에서 일어나는 미묘한 변화로 구별할 수 있네. "
|
"지팡이로 주문을 많이 사용할 수록 주문시전에 더 효과적이게 되고, 더 높은 등급의 주문을 시전할 수 있다네. 지팡이 자체의 모양과 모양에서 일어나는 미묘한 변화로 구별할 수 있네. "
|
||||||
,
|
,
|
||||||
"지팡이가 점점 강력해질수록 수정은 더욱 강해지고, @elements 원소@에 따라 색이 변할 수도 있으며, 지팡이의 막대기가 자라기 시작하여 더욱 복잡한 모양으로 꼬일 걸세.",
|
"지팡이가 점점 강력해질수록 수정은 더욱 강해지고, @elements 원소@에 따라 색이 변할 수도 있으며, 지팡이의 막대기가 자라기 시작하여 더욱 복잡한 모양으로 꼬일 걸세.",
|
||||||
|
|
||||||
"지팡이를 잡으면 화면 구석에 작은 HUD가 나타난다네. 현재 선택한 마법을 그림으로 표현한 것과 함께 주문이 표시되며, 마법을 시전한 후 그 주문을 다시 사용할 수 있는 시간을 나타내는 재사용 대기 막대가 표시될 걸세. 또한 지팡이에 추가된 다음 주문과 이전의 주문들의 이름을 보여준다네. 주문을 전환하려면 #next_spell_key키 및 #previous_spell_key키(설정-> 조작에서 변경할 수 있음)를 사용하면 된다네. 웅크리고 마우스를 움직이면서 마법을 바꿀 수도 있다는 것을 알아두게.",
|
"지팡이를 잡으면 화면 구석에 작은 HUD가 나타난다네. 현재 선택한 마법을 그림으로 표현한 것과 함께 주문이 표시되며, 마법을 시전한 후 그 주문을 다시 사용할 수 있는 시간을 나타내는 재사용 대기 막대가 표시될 걸세. 또한 지팡이에 추가된 다음 주문과 이전의 주문들의 이름을 보여준다네. 주문을 전환하려면 #next_spell_key키 및 #previous_spell_key키(설정-> 조작에서 변경할 수 있음)를 사용하면 된다네. 웅크리고 마우스를 움직이면서 마법을 바꿀 수도 있다는 것을 알아두게.",
|
||||||
|
|
||||||
"인벤토리로 지팡이를 볼 때, 지팡이에 마우스를 올리면 마나가 얼마나 저장되어 있는지 그리고 현재 선택된 주문과 지팡이가 가지고 있는 특별한 능력들을 볼 수 있다네. 지팡이에 대한 더 세세한 정보는 @arcane_workbench 신비로운 작업대@에 올려 보면 알 수 있다."
|
"인벤토리로 지팡이를 볼 때, 지팡이에 마우스를 올리면 마나가 얼마나 저장되어 있는지 그리고 현재 선택된 주문과 지팡이가 가지고 있는 특별한 능력들을 볼 수 있다네. 지팡이에 대한 더 세세한 정보는 @arcane_workbench 신비로운 작업대@에 올려 보면 알 수 있다네."
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -398,15 +398,15 @@
|
|||||||
],
|
],
|
||||||
"text": [
|
"text": [
|
||||||
|
|
||||||
"@wands 지팡이@는 마법이 없으면 쓸모가 없다. 마법은 영구적인 주문서와 일시적인 두루마리의 형태로 기록된다네.",
|
"@wands 지팡이@는 마법이 없으면 쓸모가 없다네. 마법은 영구적인 주문서와 일시적인 두루마리의 형태로 기록된다네.",
|
||||||
|
|
||||||
"주문서는 그 자체로는 별로 쓸모가 없다;주문서는 주문서가 가지고 있는 주문을 지팡이에 추가하는데 사용한다네. 주문서는 전세계 어디에서나 발견될 수 있고 주문서를 발견하는 데 오래 걸리지 않을 걸세. 주문서를 찾으면, 주문서에 마우스를 올려서 주문에 대한 기본적인 정보를 한눈에 볼 수 있고, 주문서를 들고 마우스 오른쪽 버튼을 클릭하여 자세한 내용을 읽을 수도 있다네.",
|
"주문서는 그 자체로는 별로 쓸모가 없다;주문서는 주문서가 가지고 있는 주문을 지팡이에 추가하는데 사용한다네. 주문서는 전세계 어디에서나 발견될 수 있고 주문서를 발견하는 데 오래 걸리지 않을 걸세. 주문서를 찾으면, 주문서에 마우스를 올려서 주문에 대한 기본적인 정보를 한눈에 볼 수 있고, 주문서를 들고 오른쪽 버튼을 클릭하여 자세한 내용을 읽을 수도 있다네.",
|
||||||
|
|
||||||
"반면 두루마리는 다른 용도로 사용된다네. 마우스 오른쪽 버튼을 누르면 해당 두루마리에 걸려 있는 마법이 시전되고 두루마리가 파괴될걸세. 주문서처럼 두루마리도 전세계 어디에서나 찾아볼 수 있지만 직접 만들 수도 있다네. (@enchanting_scrolls 마법이 부여된 두루마리@ 참조)",
|
"반면 두루마리는 다른 용도로 사용된다네. 오른쪽 버튼을 누르면 해당 두루마리에 걸려 있는 마법이 시전되고 두루마리가 파괴될걸세. 주문서처럼 두루마리도 전세계 어디에서나 찾아볼 수 있지만 직접 만들 수도 있다네. (@enchanting_scrolls 마법이 부여된 두루마리@ 참조)",
|
||||||
|
|
||||||
"두루마리는 특정 상황에서 한 두 번 마법을 사용해야 할 때 꽤 유용하지만, @wands 지팡이@의 공간이 부족할때 쓸만한 수단이네. 또한 충전 시간이 필요한 주문을 즉시 시전할 수 있다는 이점이 있다네. 단, 지팡이를 사용하는 것에 비해 비효율적인 방법이라는 점을 유의하게.",
|
"두루마리는 특정 상황에서 한 두 번 마법을 사용해야 할 때 꽤 유용하지만, @wands 지팡이@의 공간이 부족할때 쓸만한 수단이네. 또한 충전 시간이 필요한 주문을 즉시 시전할 수 있다는 이점이 있다네. 단, 지팡이를 사용하는 것에 비해 비효율적인 방법이라는 점을 유의하게.",
|
||||||
|
|
||||||
"식별하지 않은 사람의 눈으로는 주문에 쓰여진 마법의 룬문자를 읽을 수 없다네. 주문을 식별하기 위해서는, 주문을 시전하면 된다네.시전하면 가끔 원치 않는 부작용이 일어날걸세. 많은 주문들은 시전하기 위해 특정한 조건이 필요하다네. 더 나아가, 알 수 없는 주문을 시전할 때 잘못 읽을 가능성도 있으며, 그 주문이 얼마나 강력한지에 따라 잠재적으로 위험한 부작용를 초래할 수 있다네. 안전한 방법은 상자에서 발견하거나 마법사에게 구입할 수 있는 지식의 두루마리를 사용하는 것이다. 손에 들고 마우스 오른쪽 버튼을 클릭하면 단축바에 가장 앞에 있는 주문서나 두루마리를 식별하며, 이 과정에서 지식의 두루마리를 소비할걸세."
|
"식별하지 않은 사람의 눈으로는 주문에 쓰여진 마법의 룬문자를 읽을 수 없다네. 주문을 식별하기 위해서는, 주문을 시전하면 된다네.시전하면 가끔 원치 않는 부작용이 일어날걸세. 많은 주문들은 시전하기 위해 특정한 조건이 필요하다네. 더 나아가, 알 수 없는 주문을 시전할 때 잘못 읽을 가능성도 있으며, 그 주문이 얼마나 강력한지에 따라 잠재적으로 위험한 부작용를 초래할 수 있다네. 안전한 방법은 상자에서 발견하거나 마법사에게 구입할 수 있는 지식의 두루마리를 사용하는 것이네. 손에 들고 오른쪽 버튼을 클릭하면 단축바에 가장 앞에 있는 주문서나 두루마리를 식별하며, 이 과정에서 지식의 두루마리를 소비할걸세."
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -441,7 +441,7 @@
|
|||||||
],
|
],
|
||||||
"text": [
|
"text": [
|
||||||
|
|
||||||
"신비로운 작업대의 중앙 슬롯에 지팡이를 놓고 주변의 슬롯 중 하나에 주문서를 놓고 적용 버튼을 누르면 지팡이에 주문이 추가될걸세. 이 과정에서 주문서는 움직이지 않는데, 주문을 추가하는 것이 주문서의 주문을 '가져'가는 것이 아니기 때문이라네. 오히려 주문서가 주문에 맞추어 지팡이에 붙는다네. 이처럼 단순히 원하는 만큼 지팡이에 추가되는 마법을 바꿀 수도 있다네. 한 번에 최대 5개의 주문을 지팡이에 추가할 수 있지만, `주문 허용량 강화` 로 증가시킬 수 있다네."
|
"신비로운 작업대의 중앙 슬롯에 지팡이를 놓고 주변의 슬롯 중 하나에 주문서를 놓고 적용 버튼을 누르면 지팡이에 주문이 추가될걸세. 이 과정에서 주문서는 움직이지 않는데, 주문을 추가하는 것이 주문서의 주문을 '가져'가는 것이 아니기 때문이라네. 오히려 주문서가 주문에 맞추어 지팡이에 붙는다네. 이처럼 단순히 원하는 만큼 지팡이에 추가되는 마법을 바꿀 수도 있다네. 한 번에 최대 5개의 주문을 지팡이에 추가할 수 있지만, `주문 허용량 강화` 로 증가시킬 수 있다네."
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"charging_wands": {
|
"charging_wands": {
|
||||||
@@ -452,7 +452,7 @@
|
|||||||
],
|
],
|
||||||
"text": [
|
"text": [
|
||||||
|
|
||||||
"신비로운 작업대의 중앙 슬롯에 지팡이를 놓고 왼쪽 아래 슬롯에 마법 수정을 놓고 적용 버튼을 누르면 지팡이가 충전될걸세. 각 마법수정은 #mana_per_crystal마나의 값어치가 있고, 지팡이는 필요할 때까지 수정을 사용하기 때문에, 마나를 충전할 때 생각하고 충전해야 한다네. 지팡이는 수정을 #mana_per_crystal마나 만큼씩 회복할 수 있음으로, 예를 들어 30마나가 더 필요할 경우 충전할 때 #example_charging_loss마나가 손실된다네."
|
"신비로운 작업대의 중앙 슬롯에 지팡이를 놓고 왼쪽 아래 슬롯에 마법 수정을 놓고 적용 버튼을 누르면 지팡이가 충전될걸세. 각 마법수정은 #mana_per_crystal마나의 값어치가 있고, 지팡이는 필요할 때까지 수정을 사용하기 때문에, 마나를 충전할 때 생각하고 충전해야 한다네. 지팡이는 수정을 #mana_per_crystal마나 만큼씩 회복할 수 있음으로, 예를 들어 30만큼의 마나가 더 필요할 경우 충전할 때 #example_charging_loss만큼의 마나가 손실된다네."
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"upgrading_wands": {
|
"upgrading_wands": {
|
||||||
@@ -463,9 +463,9 @@
|
|||||||
],
|
],
|
||||||
"text": [
|
"text": [
|
||||||
|
|
||||||
"지팡이를 강화하려면 적절한 등급의 마도서 또는 특별한 지팡이 강화가 필요하다네. 이 두 가지 모두 약탈품으로 발견되거나 마법사에서 살 수 있다네. 지팡이를 강화하려면 중앙 슬롯에 놓고 오른쪽 위 슬롯에 강화의 재료를 놓은 다음 적용 버튼을 누르면 된다네.",
|
"지팡이를 강화하려면 적절한 등급의 마도서 또는 특별한 지팡이 강화가 필요하다네. 이 두 가지 모두 약탈품으로 발견되거나 마법사에서 살 수 있다네. 지팡이를 강화하려면 중앙 슬롯에 놓고 오른쪽 위 슬롯에 강화의 재료를 놓은 다음 적용 버튼을 누르면 된다네.",
|
||||||
|
|
||||||
"특별한 지팡이 강화는 지팡이의 특정 능력을 강화한다네. 각각의 강화는 최대 3회까지 쌓을 수 있으며, 지팡이가 할 수 있는 강화의 총수는 해당 등급에 따라 달라진다네. 또한 강화는 제거할 수 없다는 것을 명심하게."
|
"특별한 지팡이 강화는 지팡이의 특정 능력을 강화한다네. 각각의 강화는 최대 3회까지 쌓을 수 있으며, 지팡이가 할 수 있는 강화의 총수는 해당 등급에 따라 달라진다네. 또한 강화는 제거할 수 없다는 것을 명심하게."
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"enchanting_scrolls": {
|
"enchanting_scrolls": {
|
||||||
@@ -476,7 +476,7 @@
|
|||||||
],
|
],
|
||||||
"text": [
|
"text": [
|
||||||
|
|
||||||
"신비로운 작업대는 또한 빈 두루마리에 마법을 부여하는데 사용할 수 있다네. 먼저, 종이 한 장과 끈으로 만든 빈 두루마리와 주문서, 그리고 마법을 부여할 마나를 제공할 수 있는 마법수정이 필요할 것이네.",
|
"신비로운 작업대는 또한 빈 두루마리에 마법을 부여하는데 사용할 수 있다네. 먼저, 종이 한 장과 끈으로 만든 빈 두루마리와 주문서, 그리고 마법을 부여할 마나를 제공할 수 있는 마법수정이 필요할 것이네.",
|
||||||
|
|
||||||
"#recipe blank_scroll",
|
"#recipe blank_scroll",
|
||||||
|
|
||||||
@@ -495,7 +495,7 @@
|
|||||||
],
|
],
|
||||||
"text": [
|
"text": [
|
||||||
|
|
||||||
"마법사로서, 강력한 적으로부터 보호할 무언가가 필요할 걸세. 하지만 평범한 갑옷은 안 된다네. 주문을 최대한 활용하려면 모자, 로브, 각반, 부츠 등 마법사의 특별한 갑옷이 필요하다네. 이 갑옷은 일반적인 갑옷과는 달리, 부서지지 않는다네. 대신, 이 갑옷은 착용자를 보호하기 위해 신비로운 에너지를 사용한다네. 즉, 지팡이처럼 마법수정으로 마나를 충전해야 한다는 것일세. 다행히 이 옷들은 마나를 많이 소모하지 않는다네. 신비로운 작업대나 @mana_flasks 마나병@으로 간단하게 충전할 수 있다네. 그러나, 마나가 떨어지면 방어력이 현저히 떨어져 위험에 놓일 수도 있다네.",
|
"마법사로서, 강력한 적으로부터 보호할 무언가가 필요할 걸세. 하지만 평범한 갑옷은 안 된다네. 주문을 최대한 활용하려면 모자, 로브, 각반, 부츠 등 마법사의 특별한 갑옷이 필요하다네. 이 갑옷은 일반적인 갑옷과는 달리, 부서지지 않는다네. 대신, 이 갑옷은 착용자를 보호하기 위해 신비로운 에너지를 사용한다네. 즉, 지팡이처럼 마법수정으로 마나를 충전해야 한다는 것일세. 다행히 이 옷들은 마나를 많이 소모하지 않는다네. 신비로운 작업대나 @mana_flasks 마나병@으로 간단하게 충전할 수 있다네. 그러나, 마나가 떨어지면 방어력이 현저히 떨어져 위험에 놓일 수도 있다네.",
|
||||||
|
|
||||||
"#image wizard_armour",
|
"#image wizard_armour",
|
||||||
|
|
||||||
@@ -507,17 +507,17 @@
|
|||||||
"#recipe wizard_leggings",
|
"#recipe wizard_leggings",
|
||||||
"#recipe wizard_boots",
|
"#recipe wizard_boots",
|
||||||
|
|
||||||
"기본 마법 부여대를 사용하여 마법사의 갑옷에 마법부여를 할 수 있으며, 마법의 비단 고유의 특성 때문에 마법부여를 받는 데 상당히 효과적인 경향이 있다네. 마법사의 갑옷의 특별한 마법부여로는 마법, 빙결 및 충격 보호 마법이 있는데, 다른 마법을 사용하는 자들과 싸울 때 유리하게 작용할걸세.",
|
"기본 마법 부여대를 사용하여 마법사의 갑옷에 마법부여를 할 수 있으며, 마법의 비단 고유의 특성 때문에 마법부여를 받는 데 상당히 효과적인 경향이 있다네. 마법사의 갑옷의 특별한 마법부여로는 마법, 빙결 및 충격 보호 마법이 있는데, 다른 마법을 사용하는 자들과 싸울 때 유리하게 작용할걸세.",
|
||||||
|
|
||||||
"아주 특별한 마법사들은 특정 원소에 영향을 주는 특별한 옷을 입는다네. 그 특별한 마법사의 갑옷은 찾기가 쉽지 않다네.",
|
"아주 특별한 마법사들은 특정 원소에 영향을 주는 특별한 옷을 입는다네. 그 특별한 마법사의 갑옷은 찾기가 쉽지 않다네.",
|
||||||
|
|
||||||
"마법의 기본을 터득한 후에는 많은 마법사들이 훈련을 하기 위해 특별한 경로를 따라가거나 분야를 선택하게 된다네. 가장 주된 분야로는 학자와 전투법사 , 주술사 총 3가지가 있다네. 각 분야의 로브는 특이한 외형과 특성을 가지고 있는데 각 분야의 마법사들을 쉽게 구별하고 각 분야의 목적에 맞추기 위해 희귀하고 특이한 재료로 로브를 변형하였기 때문이라네. ",
|
"마법의 기본을 터득한 후에는 많은 마법사들이 훈련을 하기 위해 특별한 경로를 따라가거나 분야를 선택하게 된다네. 가장 주된 분야로는 학자와 전투법사, 주술사 총 3가지가 있다네. 각 분야의 로브는 특이한 외형과 특성을 가지고 있는데 각 분야의 마법사들을 쉽게 구별하고 각 분야의 목적에 맞추기 위해 희귀하고 특이한 재료로 로브를 변형하였기 때문이라네. ",
|
||||||
|
|
||||||
"#image classes",
|
"#image classes",
|
||||||
|
|
||||||
"학자",
|
"학자",
|
||||||
|
|
||||||
"지식을 추구하기 위해 삶을 바치면서, 학자는 완벽하게 효율적인 시전 방법을 연구하여 , 가능한 한 적은 양의 마나를 사용하여 마법을 시전할 수 있게 됐다네. 학자의 비단 로브의 화려함에는 상당한 보호 기능이 있다네. 학자는 뛰어난 마법 부여로 실력으로 로브에 마법을 부여하기 때문이네. 그러나 이 비단 로브는 고체 금속을 도금한 갑옷과는 비교가 되지도 않는다네. 그리고 안전한 도서관에서 긴 시간을 보내는 학자의 특성상 전투에 더욱더 더디게 만드는 데 한몫했을걸세",
|
"지식을 추구하기 위해 삶을 바치면서, 학자는 완벽하게 효율적인 시전 방법을 연구하여, 가능한 한 적은 양의 마나를 사용하여 마법을 시전할 수 있게 됐다네. 학자의 비단 로브의 화려함에는 상당한 보호 기능이 있다네. 학자는 뛰어난 마법 부여로 실력으로 로브에 마법을 부여하기 때문이네. 그러나 이 비단 로브는 고체 금속을 도금한 갑옷과는 비교가 되지도 않는다네. 그리고 안전한 도서관에서 긴 시간을 보내는 학자의 특성상 전투에 더욱더 더디게 만드는 데 한몫했을걸세",
|
||||||
|
|
||||||
"전투법사",
|
"전투법사",
|
||||||
|
|
||||||
@@ -545,7 +545,7 @@
|
|||||||
|
|
||||||
"집에서 연구만 한다고 해서 불가사의한 마법을 정복할 수는 없다네. 마법이 가득한 세상은 바로밖에 있다네! 고대 유적과 유물, 그리고 선악 무도한 존재들이 기다리고 있다네. 위대한 마법사들도 호기심이 많고 주변 환경 탐사와 그들이 발견한 것을 실험함으로써 지식과 힘을 많이 얻는다네.",
|
"집에서 연구만 한다고 해서 불가사의한 마법을 정복할 수는 없다네. 마법이 가득한 세상은 바로밖에 있다네! 고대 유적과 유물, 그리고 선악 무도한 존재들이 기다리고 있다네. 위대한 마법사들도 호기심이 많고 주변 환경 탐사와 그들이 발견한 것을 실험함으로써 지식과 힘을 많이 얻는다네.",
|
||||||
|
|
||||||
"마법사는 시간의 많은 부분을 불가피하게 혼자 보내지만, 지식의 공유는 마법을 배우는 데 거의 필수적이라네. 마법의 대가들을 찾고, 가능한 한 많이 배우라네: 의사소통은 틀림없이 가장 큰 힘이 될 것이네."
|
"마법사는 시간의 많은 부분을 불가피하게 혼자 보내지만, 지식의 공유는 마법을 배우는 데 거의 필수적이라네. 마법의 대가들을 찾고, 가능한 한 많이 배우라네. 의사소통은 틀림없이 가장 큰 힘이 될 것이네."
|
||||||
],
|
],
|
||||||
"sections": {
|
"sections": {
|
||||||
"crystal_flowers": {
|
"crystal_flowers": {
|
||||||
@@ -556,7 +556,7 @@
|
|||||||
],
|
],
|
||||||
"text": [
|
"text": [
|
||||||
|
|
||||||
"여행하는 동안, 가끔 야생에서 자라는 기이한 빛나는 꽃을 보게 될걸세. 이 독특한 꽃은 마법수정 꽃으로 알려져 있고, 마력을 집중시키는 특이한 성질을 지니고 있다네, 오늘날까지, 아무도 왜 그런지 모른다네. 그 꽃을 수확하여 마법수정으로 추출할 수 있다네. 그러나, 지상의 마나의 원천이 될 정도로 많은 양의 마나를 얻기 힘들다네.",
|
"여행하는 동안, 가끔 야생에서 자라는 기이한 빛나는 꽃을 보게 될걸세. 이 독특한 꽃은 마법수정 꽃으로 알려져 있고, 마나를 집중시키는 특이한 성질을 지니고 있다네, 오늘날까지, 아무도 왜 그런지 모른다네. 그 꽃을 수확하여 마법수정으로 추출할 수 있다네. 그러나, 지상의 마나의 원천이 될 정도로 많은 양의 마나를 얻기 힘들다네.",
|
||||||
|
|
||||||
"#image crystal_flower",
|
"#image crystal_flower",
|
||||||
"#recipe crystal_flower_to_crystals"
|
"#recipe crystal_flower_to_crystals"
|
||||||
@@ -570,15 +570,15 @@
|
|||||||
],
|
],
|
||||||
"text": [
|
"text": [
|
||||||
|
|
||||||
"이 세상에는 많은 마법사가 존재한다네. 여행 중에, 독특한 뾰족한 지붕을 가진 한두 개의 높은 탑과 마주칠 수도 있을걸세. 이곳은 바로 마법사의 거주지라네. 때때로 마법사들은 고독을 즐기지만, 그들은 거의 대가를 치르더라도 기꺼이 지식을 공유하려는 친절한 사람들이라네. 귀금속과 보석을 지불하면, 그 대가로 많은 신비로운 물건을 받게 될 것이라네.",
|
"이 세상에는 많은 마법사가 존재한다네. 여행 중에, 독특한 뾰족한 지붕을 가진 한두 개의 높은 탑과 마주칠 수도 있을걸세. 이곳은 바로 마법사의 거주지라네. 때때로 마법사들은 고독을 즐기지만, 그들은 거의 대가를 치르더라도 기꺼이 지식을 공유하려는 친절한 사람들이라네. 귀금속과 보석을 지불하면, 그 대가로 많은 신비로운 물건을 받게 될 것이라네.",
|
||||||
|
|
||||||
"그러나, 찾는 주문이 @tiers 대가@주문이라면, 전문적인 마법사를 찾을 필요가 있다네.",
|
"그러나, 찾는 주문이 @tiers 대가@주문이라면, 전문적인 마법사를 찾을 필요가 있다네.",
|
||||||
|
|
||||||
"#image wizard_tower",
|
"#image wizard_tower",
|
||||||
|
|
||||||
"불행히도, 방문객을 환영하지 않는 몇몇 마법사들이 있다네. 이 마법사는 추방을 당한 마법사며, 지나가는 모든 사람에게 적대적이라네. 그 마법사는 강력한 마법들을 사용하므로 자신을 방어할 준비를 하고 다가가야 한다네. 그렇게 그들을 물리치면, 그들의 지식을 빼앗아 사용할 수 있다네.",
|
"불행히도, 방문객을 환영하지 않는 몇몇 마법사들이 있다네. 이 마법사는 추방을 당한 마법사며, 지나가는 모든 사람에게 적대적이라네. 그 마법사는 강력한 마법들을 사용하므로 자신을 방어할 준비를 하고 다가가야 한다네. 그렇게 그들을 물리치면, 그들의 지식을 빼앗아 사용할 수 있다네.",
|
||||||
|
|
||||||
"또한 어떤 마법사도 공격이나 도난당하는 것을 좋게 받아들이지 않을 것이고, 그들이 반대로 공격할 수 있다는 것을 알아두게"
|
"또한 어떤 마법사도 공격이나 도난당하는 것을 좋게 받아들이지 않을 것이고, 그들이 반대로 공격할 수 있다는 것을 알아두게"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"obelisks": {
|
"obelisks": {
|
||||||
@@ -591,26 +591,26 @@
|
|||||||
|
|
||||||
"고대 마법의 흔적은 전 세계에 흩어져 있으며, 그중 가장 눈에 띄는 구조물은 많은 상징과 룬문자가 새겨진 돌로 구성된 석조건물이라네. 이 유적들은 고대 문명의 일부로 보이는 것들로 이루어져 있다네. 누가 지었든 간에, 분명히 마법에 대한 상당한 지식을 가지고 있었고, 그 산물을 오늘날까지 지속하고 있는 보호 마법으로 막아두었다네.",
|
"고대 마법의 흔적은 전 세계에 흩어져 있으며, 그중 가장 눈에 띄는 구조물은 많은 상징과 룬문자가 새겨진 돌로 구성된 석조건물이라네. 이 유적들은 고대 문명의 일부로 보이는 것들로 이루어져 있다네. 누가 지었든 간에, 분명히 마법에 대한 상당한 지식을 가지고 있었고, 그 산물을 오늘날까지 지속하고 있는 보호 마법으로 막아두었다네.",
|
||||||
|
|
||||||
"이 구조물은 두 가지로 나누어지는데, 첫 번째로, 가장 쉽게 찾을 수 있는 방첨탑이 있다네: 룬문자가 새겨진 돌로 이루어진 길고 뾰족한 방첨탑은 개방되어 있고 잊힌 과거의 @artefacts 유물@이 들어 있는 작은 상자가 있다네.",
|
"이 구조물은 두 가지로 나누어지는데, 첫 번째로, 가장 쉽게 찾을 수 있는 방첨탑이 있다네: 룬문자가 새겨진 돌로 이루어진 길고 뾰족한 방첨탑은 개방되어 있고 잊힌 과거의 @artefacts 유물@이 들어 있는 작은 상자가 있다네.",
|
||||||
|
|
||||||
"#image obelisk",
|
"#image obelisk",
|
||||||
|
|
||||||
"방첨탑은 인간이 가까히 다가오면 적대적인 @creatures 마법의 생명체@를 소환한다네. 생명체를 유의하여 상자를 열면 유물을 얻을 수도 있다네."
|
"방첨탑은 인간이 가까히 다가오면 적대적인 @creatures 마법의 생명체@를 소환한다네. 생명체를 유의하여 상자를 열면 유물을 얻을 수도 있다네."
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"shrines": {
|
"shrines": {
|
||||||
"title": "신사",
|
"title": "사당",
|
||||||
"include_in_contents": "magical_world_subsections",
|
"include_in_contents": "magical_world_subsections",
|
||||||
"triggers": [
|
"triggers": [
|
||||||
"ebwizardry:visit_shrine"
|
"ebwizardry:visit_shrine"
|
||||||
],
|
],
|
||||||
"text": [
|
"text": [
|
||||||
|
|
||||||
"두 번째로, 방첨탑 보다 희귀한 구조물인 신사가 있다네. 이 구조물은 중앙 받침대를 원형으로 기둥이 둘러싸고 있는 모습이고, 그 위에 고대 @artefacts 유물@이 있는 상자가 놓여 있다네. 이 상자는 일반적으로 마법 잠금 마법에 의해 보호되어 있어서 주인 이외에는 아무도 그것을 열지 못한다네. 또한 신사 전체가 봉쇄 마법으로 보호되어 있어 가까이 있는 모든 것을 빠져나지 못하게 한다네.",
|
"두 번째로, 방첨탑 보다 희귀한 구조물인 사당이 있다네. 이 구조물은 중앙 받침대를 원형으로 기둥이 둘러싸고 있는 모습이고, 그 위에 고대 @artefacts 유물@이 있는 상자가 놓여 있다네. 이 상자는 일반적으로 마법 잠금 마법에 의해 보호되어 있어서 주인 이외에는 아무도 그것을 열지 못한다네. 또한 사당 전체가 봉쇄 마법으로 보호되어 있어 가까이 있는 모든 것을 빠져나지 못하게 한다네.",
|
||||||
|
|
||||||
"#image shrine",
|
"#image shrine",
|
||||||
|
|
||||||
"신사는 불가사의한 힘과 의미 때문에, 돈으로서의 가치는 말할 것도 없고, 특히 출세를 노리는 마법사에게 매력적이지만, 마법사들이 봉쇄된 신사 안에 갇혀 서서히 미쳐가고 있다는 수많은 보고가 있다네. 점점 더 많은 사람이 그러한 불가사의한 사당의 봉쇄 마법에 잡힌 것은 의도적인 신사의 구조이고, 그 안에 갇힌 마법사들은 사실 그 구조를 보호하기 위해 통제되고 있다고 추론된다네."
|
"사당은 불가사의한 힘과 의미 때문에, 돈으로서의 가치는 말할 것도 없고, 특히 출세를 노리는 마법사에게 매력적이지만, 마법사들이 봉쇄된 사당 안에 갇혀 서서히 미쳐가고 있다는 수많은 보고가 있다네. 점점 더 많은 사람이 그러한 불가사의한 사당의 봉쇄 마법에 잡힌 것은 의도적인 사당의 구조이고, 그 안에 갇힌 마법사들은 사실 그 구조를 보호하기 위해 통제되고 있다고 추론된다네."
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"library_ruins": {
|
"library_ruins": {
|
||||||
@@ -625,9 +625,9 @@
|
|||||||
|
|
||||||
"#image library_ruins",
|
"#image library_ruins",
|
||||||
|
|
||||||
"도서관은 단순히 책을 저장하는 데만 사용되는 것은 아니라네. 과거의 마법사들은 마법물질에 대한 원소적 고취의 의식을 행하는 데 사용되는 고취의 제단의 힘을 사용했다네. 제단의 위치는 특정한 천체의 움직임과 작은 마나 변동에 따라 정렬되어야 하기 때문에 정확하고 어려운 기술이라네. 제단을 만드는 관습은 최근 희귀해졌는데, 주로 한번 지어지면 제단이 수세기 동안 지속되기 때문에 새로운 제단은 필요하지 않기 때문이라네. 대신, 대부분의 마법사들은 고취의 의식을 행할 필요가 있을 때 기존의 제단을 찾아서 수리한다네.",
|
"도서관은 단순히 책을 저장하는 데만 사용되는 것은 아니라네. 과거의 마법사들은 마법물질에 대한 원소적 주입 의식을 행하는 데 사용되는 주입의 제단의 힘을 사용했다네. 제단의 위치는 특정한 천체의 움직임과 작은 마나의 변동에 따라 정렬되어야 하기 때문에 정확하고 어려운 기술이라네. 제단을 만드는 관습은 최근 희귀해졌는데, 주로 한번 지어지면 제단이 수세기 동안 지속되기 때문에 새로운 제단은 필요하지 않기 때문이라네. 대신, 대부분의 마법사들은 주입 의식을 행할 필요가 있을 때 기존의 제단을 찾아서 수리한다네.",
|
||||||
|
|
||||||
"나중에, 언젠가 나만의 도서관을 지어 주문서를 보관할 때가 생길 것이다. 도서관에 필요한 것들을 만드는 방법:",
|
"나중에, 언젠가 나만의 도서관을 지어 주문서를 보관할 때가 생길 것이네. 도서관에 필요한 것들을 만드는 방법:",
|
||||||
|
|
||||||
"#recipe bookshelves",
|
"#recipe bookshelves",
|
||||||
|
|
||||||
@@ -648,9 +648,9 @@
|
|||||||
],
|
],
|
||||||
"text": [
|
"text": [
|
||||||
|
|
||||||
"마법사 외에도, 많은 생물들은 마법을 사용한다네. 이 생물 중 대부분 기원이 불가사의하며, 대부분은 특정 마법 주문으로 소환할 수 있다네. @obelisks 방첨탑@에서도 강력한 소환사를 지키고 있는 이 생물들과 마주칠지도 모른다네. 또한, 이 불가사의한 존재는 황야에서 가끔 발견되기도 한다네.",
|
"마법사 외에도, 많은 생물들은 마법을 사용한다네. 이 생물 중 대부분 기원이 불가사의하며, 대부분은 특정 마법 주문으로 소환할 수 있다네. @obelisks 방첨탑@에서도 강력한 소환사를 지키고 있는 이 생물들과 마주칠지도 모른다네. 또한, 이 불가사의한 존재는 황야에서 가끔 발견되기도 한다네.",
|
||||||
" ",
|
" ",
|
||||||
"눈에 띄는 예로는 강력한 마법이 남긴 흔적에서 자연히 형성되어 일곱 개의 신비로운 @elements 원소@ 중 하나를 떠맡는 망령 같은 존재인 잔존체이라네. 잔존체는 하나만 있다면, 성가신 것에 지나지 않지만 모여있으면 준비되지 않은 모험가를 쉽게 압도할 수 있고, 마법에 대한 저항이 있어, 활이나 다른 원거리 무기를 휴대하는 것이 좋다네.",
|
"눈에 띄는 예로는 강력한 마법이 남긴 흔적에서 자연히 형성되어 일곱 개의 신비로운 @elements 원소@ 중 하나를 떠맡는 망령 같은 존재인 잔존체이라네. 잔존체는 하나만 있다면, 성가신 것에 지나지 않지만 모여있으면 준비되지 않은 모험가를 쉽게 압도할 수 있고, 마법에 대한 저항이 있어, 활이나 다른 원거리 무기를 휴대하는 것이 좋다네.",
|
||||||
|
|
||||||
"#image remnant",
|
"#image remnant",
|
||||||
|
|
||||||
@@ -669,7 +669,7 @@
|
|||||||
],
|
],
|
||||||
"text": [
|
"text": [
|
||||||
|
|
||||||
"@shrines 신사@를 탐험할 때, 운이 좋다면 독특하고 강력한 효과와 특별한 힘이 있는 고대 마법의 유물을 발견할 수 있을걸세. 추가 효과를 부여하는 반지, 수비능력을 향상하는 목걸이, 특별한 효과를 부여하는 부적 등 3가지만이 발견된 것으로 알려져 있다네. 이 유물은 특정한 상황에서 효과를 발휘하므로; 단순히 몸에 지닌 것은 효과를 기대하기 힘들다네."
|
"@shrines 사당@을 탐험할 때, 운이 좋다면 독특하고 강력한 효과와 특별한 힘이 있는 고대 마법의 유물을 발견할 수 있을걸세. 추가 효과를 부여하는 반지, 수비능력을 향상하는 목걸이, 특별한 효과를 부여하는 부적 등 3가지만이 발견된 것으로 알려져 있다네. 이 유물은 특정한 상황에서 효과를 발휘하므로; 단순히 몸에 지닌 것은 효과를 기대하기 힘들다네."
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -683,19 +683,19 @@
|
|||||||
],
|
],
|
||||||
"text":[
|
"text":[
|
||||||
|
|
||||||
"지팡이와 주문은 4개의 등급으로 이루어져있다네: #colour_novice초보#colour_reset와 #colour_apprentice견습#colour_reset, #colour_advanced숙련#colour_reset과 #colour_master대가#colour_reset. 각 등급은 마지막 등급으로 갈 수록 더 강력하다네.",
|
"지팡이와 주문은 4개의 등급으로 이루어져있다네: #colour_novice초보#colour_reset와 #colour_apprentice견습#colour_reset, #colour_advanced숙련#colour_reset과 #colour_master대가#colour_reset. 각 등급은 마지막 등급으로 갈수록 더 강력하다네.",
|
||||||
|
|
||||||
"#image tiers",
|
"#image tiers",
|
||||||
" ",
|
" ",
|
||||||
"#colour_novice초보 #colour_reset지팡이는 만들 수 있는 지팡이라네. 최대 #novice_max_charge 마나를 가지고 있으며, 초보적인 주문만 시전할 수 있네. 초보 주문은 누구나 시전할 수 있을 정도로 간단하며 보통, 마나이 많이 들지 않는다네. 그렇다고, 더 높은 등급에서 쓸모없다는 것을 의미하지는 않는다네; 초보 주문의 낮은 재사용 시간 덕분에 대가의 주문을 쓸 수 있어도 초보 주문은 유용하게 사용할 수 있다네.",
|
"#colour_novice초보 #colour_reset지팡이는 만들 수 있는 지팡이라네. 최대 #novice_max_charge 마나를 가지고 있으며, 초보적인 주문만 시전할 수 있네. 초보 주문은 누구나 시전할 수 있을 정도로 간단하며 보통, 마나이 많이 들지 않는다네. 그렇다고, 더 높은 등급에서 쓸모없다는 것을 의미하지는 않는다네; 초보 주문의 낮은 재사용 시간 덕분에 대가의 주문을 쓸 수 있어도 초보 주문은 유용하게 사용할 수 있다네.",
|
||||||
" ",
|
" ",
|
||||||
"#colour_apprentice견습 #colour_reset지팡이는 초보 지팡이보다 높은 등급이라네. 최대 #apprentice_max_charge 마나를 가지고 있으며, 초보와 견습 마법을 시전할 수 있다네. 견습 주문은 초보 주문보다 조금 더 강력하지만, 보통 마나가 더 많이 든다네. #colour_advanced숙련 #colour_reset지팡이는 희귀하고 훨씬 더 강력하다네. 대가 마법을 제외한 모든 마법을 시전할 수 있고, #advanced_max_charge 마나를 가지고 있으며, 고급 주문은 보이지 않는 것과 같은 초인적인 힘을 제어할 수 있고 적에게 엄청난 혼란을 줄 수 있다네.",
|
"#colour_apprentice견습 #colour_reset지팡이는 초보 지팡이보다 높은 등급이라네. 최대 #apprentice_max_charge 마나를 가지고 있으며, 초보와 견습 마법을 시전할 수 있다네. 견습 주문은 초보 주문보다 조금 더 강력하지만, 보통 마나가 더 많이 든다네. #colour_advanced숙련 #colour_reset지팡이는 희귀하고 훨씬 더 강력하다네. 대가 마법을 제외한 모든 마법을 시전할 수 있고, #advanced_max_charge 마나를 가지고 있으며, 고급 주문은 보이지 않는 것과 같은 초인적인 힘을 제어할 수 있고 적에게 엄청난 혼란을 줄 수 있다네.",
|
||||||
|
|
||||||
"#colour_master대가 #colour_reset지팡이는 현존하는 가장 강력한 지팡이라네. 최대 #master_max_charge 마나를 가지고 있으며, 어떤 주문도 시전할 수 있다네. 대가의 주문은 매우 드물고 주문은 적들뿐만 아니라 심지어 세계 그 자체에게도 완전한 파괴를 일으킬 수 있을 위력을 가지고 있다네. 주의해서 사용하게나.",
|
"#colour_master대가 #colour_reset지팡이는 현존하는 가장 강력한 지팡이라네. 최대 #master_max_charge 마나를 가지고 있으며, 어떤 주문도 시전할 수 있다네. 대가의 주문은 매우 드물고 주문은 적들뿐만 아니라 심지어 세계 그 자체에게도 완전한 파괴를 일으킬 수 있을 위력을 가지고 있다네. 주의해서 사용하게나.",
|
||||||
|
|
||||||
"더 높은 등급으로 강화하기 위해서는 지팡이가 먼저 그 등급의 마법을 쓸 수 있을 만큼 충분히 강력해져야 한다네. 지팡이는 마법과 함께 힘을 얻는다네. 주문의 다양성, 주문의 힘, 원소의 효과 및 기타 외부 요인들은 지팡이가 얼마나 빨리 성장하는지에 영향을 미칠 수 있다네.",
|
"더 높은 등급으로 강화하기 위해서는 지팡이가 먼저 그 등급의 마법을 쓸 수 있을 만큼 충분히 강력해져야 한다네. 지팡이는 마법과 함께 힘을 얻는다네. 주문의 다양성, 주문의 힘, 원소의 효과 및 기타 외부 요인들은 지팡이가 얼마나 빨리 성장하는지에 영향을 미칠 수 있다네.",
|
||||||
|
|
||||||
"지팡이가 충분히 강력해지면, 마도서로 지팡이를 다음 등급으로 끌어올리는 촉매제로 사용할 수 있다네 (@upgrading_wands 지팡이 강화@ 참조)."
|
"지팡이가 충분히 강력해지면, 마도서로 지팡이를 다음 등급으로 끌어올리는 촉매제로 사용할 수 있다네 (@upgrading_wands 지팡이 강화@ 참조)."
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -712,19 +712,19 @@
|
|||||||
|
|
||||||
"#image elements",
|
"#image elements",
|
||||||
|
|
||||||
"#colour_fire화염#colour_reset \n가장 파괴적인 속성인 화염은 불타는 것과 용암과 폭발을 우려한다네. 강력한 겁화술사가 적들에게 지옥을 방출하여, 세계를 빛나게 할 것이네. 대부분의 화염 공격 주문은 목표를 불타게 하여, 시간이 지남에 따라 지속적인 피해를 준다네. 화염이 적에게 아무런 영향을 미치지 않을 때도 있음으로 주의해야 하네.",
|
"#colour_fire화염#colour_reset \n가장 파괴적인 속성인 화염은 불타는 것과 용암과 폭발을 우려한다네. 강력한 겁화술사가 적들에게 지옥을 방출하여, 세계를 빛나게 할 것이네. 대부분의 화염 공격 주문은 목표를 불타게 하여, 시간이 지남에 따라 지속적인 피해를 준다네. 화염이 적에게 아무런 영향을 미치지 않을 때도 있음으로 주의해야 하네.",
|
||||||
|
|
||||||
"#colour_ice빙결#colour_reset \n빙결의 원소는 모두 차가운 것들로 이루어져 있다네. 얼음은 적들의 속도를 늦추거나 얼게 하며, 특히 화염의 생물에게 효과적이라네. 빙결 마법은 강을 건너기 위해 물을 얼리는 것과 같이 전투 밖에서 유용하게 사용될 수 있다네.",
|
"#colour_ice빙결#colour_reset \n빙결의 원소는 모두 차가운 것들로 이루어져 있다네. 얼음은 적들의 속도를 늦추거나 얼게 하며, 특히 화염의 생물에게 효과적이라네. 빙결 마법은 강을 건너기 위해 물을 얼리는 것과 같이 전투 밖에서 유용하게 사용될 수 있다네.",
|
||||||
|
|
||||||
"#colour_lightning전격#colour_reset \n이 원소는 번개, 폭풍, 날씨와 관련이 있다네. 강력한 폭풍법사는 무시할 수 없으며, 마음대로 번개를 부를 수 있는 능력을 상징하기도 한다네. 번개는 한 번에 다수의 적을 공격하고 어떤 적에게 효과적인 공격을 가한다네... 하지만, 크리퍼는 조심해야 한다네.",
|
"#colour_lightning전격#colour_reset \n이 원소는 번개, 폭풍, 날씨와 관련이 있다네. 강력한 폭풍법사는 무시할 수 없으며, 마음대로 번개를 부를 수 있는 능력을 상징하기도 한다네. 번개는 한 번에 다수의 적을 공격하고 어떤 적에게 효과적인 공격을 가한다네... 하지만, 크리퍼는 조심해야 한다네.",
|
||||||
|
|
||||||
"#colour_necromancy사령#colour_reset \n사령. 어둠과 혼돈과 죽음의 원소라네. 사령술의 괴짜들은 악으로 여겨질 때도 있지만, 보통 그렇지 않다네. 사령 주문은 @creatures 생명체@를 불러들여 싸우거나 적들의 의지를 꺾는 데 사용된다네.",
|
"#colour_necromancy사령#colour_reset \n사령. 어둠과 혼돈과 죽음의 원소라네. 사령술의 괴짜들은 악으로 여겨질 때도 있지만, 보통 그렇지 않다네. 사령 주문은 @creatures 생명체@를 불러들여 싸우거나 적들의 의지를 꺾는 데 사용된다네.",
|
||||||
|
|
||||||
"#colour_earth자연#colour_reset \n자연 주문은 동물, 식물, 바람 등 자연계를 다루는 원소라네. 자연 마법은 다양하다네. 적을 독살하는 것에서부터 날씨의 맹위를 발산하는 것까지 매우 다양한 형태로 사용된다네. 자연 주문은 공격, 방어가 가능하고 유용하다네.",
|
"#colour_earth자연#colour_reset \n자연 주문은 동물, 식물, 바람 등 자연계를 다루는 원소라네. 자연 마법은 다양하다네. 적을 독살하는 것에서부터 날씨의 맹위를 발산하는 것까지 매우 다양한 형태로 사용된다네. 자연 주문은 공격, 방어가 가능하고 유용하다네.",
|
||||||
|
|
||||||
"#colour_sorcery신비#colour_reset \n신비는 힘과 변화의 원소라네. 미지술사들은 자신의 필요에 맞게 빛, 중력, 심지어 현실 그 자체까지도 조작한다네. 신비 주문은 무엇보다도, 시전자에게 마법의 힘을 부여하거나 물체를 이동시키기 위해 사용할 수 있다네.",
|
"#colour_sorcery신비#colour_reset \n신비는 힘과 변화의 원소라네. 미지술사들은 자신의 필요에 맞게 빛, 중력, 심지어 현실 그 자체까지도 조작한다네. 신비 주문은 무엇보다도, 시전자에게 마법의 힘을 부여하거나 물체를 이동시키기 위해 사용할 수 있다네.",
|
||||||
|
|
||||||
"#colour_healing치유#colour_reset \n치유의 원소는 방어와 재생과 관련이 있다네. 성직자들은 가능한 한 자신과 아군을 보호하려고 하므로 상대한다면 어려운 상대일 수 있다네. 일반적으로 공격으로 쓰이지는 않지만, 일부 치유 주문은 정화 빛으로 언데드에게 상당한 피해를 준다네. 전투에서 치유 마법은 거의 필수라네.",
|
"#colour_healing치유#colour_reset \n치유의 원소는 방어와 재생과 관련이 있다네. 성직자들은 가능한 한 자신과 아군을 보호하려고 하므로 상대한다면 어려운 상대일 수 있다네. 일반적으로 공격으로 쓰이지는 않지만, 일부 치유 주문은 정화 빛으로 언데드에게 상당한 피해를 준다네. 전투에서 치유 마법은 거의 필수라네.",
|
||||||
|
|
||||||
"원소의 경계는 항상 구별되는 것은 아니며, 특정 주문은 7원소 이외의 원소의 특성을 지니고 있다네.",
|
"원소의 경계는 항상 구별되는 것은 아니며, 특정 주문은 7원소 이외의 원소의 특성을 지니고 있다네.",
|
||||||
|
|
||||||
@@ -755,7 +755,7 @@
|
|||||||
|
|
||||||
"아르켄더의 신비로운 충전 회사 - 모든 필요를 충족시키는 마법 물품!",
|
"아르켄더의 신비로운 충전 회사 - 모든 필요를 충족시키는 마법 물품!",
|
||||||
|
|
||||||
"이동 중에 지팡이를 재충전해야 하는 상황이 와도? 문제는 없습니다! 마나을 병으로 만들어, 단순한 유리병과 여덟 개의 마법수정으로 마나병을 만들 수 있습니다! 마나병을 사용해야 할 때, 간단히 조합으로 지팡이와 합쳐내면 쉽게 충전이 가능합니다. *",
|
"이동 중에 지팡이를 재충전해야 하는 상황이 와도? 문제는 없습니다! 마나을 병으로 만들어, 단순한 유리병과 여덟 개의 마법수정으로 마나병을 만들 수 있습니다! 마나병을 사용해야 할 때, 간단히 제작으로 지팡이와 합쳐내면 쉽게 충전이 가능합니다. *",
|
||||||
|
|
||||||
"#recipe medium_mana_flask",
|
"#recipe medium_mana_flask",
|
||||||
|
|
||||||
@@ -798,7 +798,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
"crafting_recipes": {
|
"crafting_recipes": {
|
||||||
"title": "조합법",
|
"title": "제작법",
|
||||||
"include_in_contents": "main_contents",
|
"include_in_contents": "main_contents",
|
||||||
"text": [
|
"text": [
|
||||||
|
|
||||||
@@ -842,9 +842,9 @@
|
|||||||
|
|
||||||
"디자인, 코드 및 텍스쳐: Electroblob",
|
"디자인, 코드 및 텍스쳐: Electroblob",
|
||||||
|
|
||||||
"마인크래프트 포지와 MCP에게 감사합니다. 이들이 없었다면 이 모드는 완성되지 못했을 겁니다.",
|
"마인크래프트 포지와 MCP에게 감사합니다. 이들이 없었다면 이 모드는 완성되지 못했을 겁니다.",
|
||||||
|
|
||||||
"또한 마인크래프트 모딩 커뮤니티에게도 감사합니다. 문제가 생기면 늘 대답을 해줬어요!",
|
"또한 마인크래프트 모딩 커뮤니티에게도 감사합니다. 문제가 생기면 늘 대답을 해줬어요!",
|
||||||
|
|
||||||
"마지막으로, 모드에 도움을 준 아래의 각 개인들에게 감사합니다.",
|
"마지막으로, 모드에 도움을 준 아래의 각 개인들에게 감사합니다.",
|
||||||
|
|
||||||
@@ -854,7 +854,7 @@
|
|||||||
|
|
||||||
"현지화를 담당해주신 분들:",
|
"현지화를 담당해주신 분들:",
|
||||||
|
|
||||||
"- 스페인어: MadWrist, Alsentar \n- 멕시코 스페인어: MadWrist \n- 러시아어: VilagVil, kellixon, bigenergy \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 \n- 프랑스어: Hahdrim \n- 브라질 포르투갈어: lorrampi \n- 중국어(간체): ZHENGLOC, dragon-evol, Hokorizero, TUsama, Determancer \n- 한국어: shejery, rewi_wire \n- 폴란드어: Trozuu \n- 독일어: BirdyDragon \n- 중국어(번체): chesterccj305 \n- 헝가리어: Bombadil",
|
||||||
|
|
||||||
"소리 효과를 담당해주신 분들:",
|
"소리 효과를 담당해주신 분들:",
|
||||||
|
|
||||||
@@ -862,9 +862,8 @@
|
|||||||
|
|
||||||
"더 많은 정보를 확인하시려면, @https://github.com/Electroblob77/Wizardry/wiki wiki@를 확인하세요.",
|
"더 많은 정보를 확인하시려면, @https://github.com/Electroblob77/Wizardry/wiki wiki@를 확인하세요.",
|
||||||
|
|
||||||
"모드의 소식을 확인하고 싶다면 @https://discord.gg/hs8yJP2 Discord server@에 가입하여 최신 소식, 토론 및 추가 정보를 얻으세요!"
|
"모드의 소식을 확인하고 싶다면 @https://discord.gg/hs8yJP2 Discord server@에 가입하여 최신 소식, 토론 및 추가 정보를 얻으세요!"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
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.
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 33 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user