alright alwinfy do your worst

This commit is contained in:
gamma-delta 2022-04-15 23:08:16 -05:00
commit 26853c6e30
33 changed files with 259 additions and 136 deletions

View file

@ -114,7 +114,7 @@ object HexMod {
@SubscribeEvent @SubscribeEvent
fun printPatternCount(evt: FMLLoadCompleteEvent) { fun printPatternCount(evt: FMLLoadCompleteEvent) {
HexMod.getLogger().info( getLogger().info(
PatternRegistry.getPatternCountInfo() PatternRegistry.getPatternCountInfo()
) )
} }

View file

@ -1,13 +1,16 @@
package at.petrak.hexcasting.api.misc; package at.petrak.hexcasting.api.misc;
import at.petrak.hexcasting.api.cap.Colorizer; import at.petrak.hexcasting.api.cap.Colorizer;
import at.petrak.hexcasting.api.mod.HexApiItems;
import at.petrak.hexcasting.api.cap.HexCapabilities; import at.petrak.hexcasting.api.cap.HexCapabilities;
import at.petrak.hexcasting.api.mod.HexApiItems;
import net.minecraft.Util; import net.minecraft.Util;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.FastColor; import net.minecraft.util.FastColor;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraftforge.registries.ForgeRegistries;
import java.util.UUID; import java.util.UUID;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -38,7 +41,12 @@ public record FrozenColorizer(ItemStack item, UUID owner) {
if (tag.isEmpty()) if (tag.isEmpty())
return FrozenColorizer.DEFAULT.get(); return FrozenColorizer.DEFAULT.get();
try { try {
var item = ItemStack.of(tag.getCompound(TAG_STACK)); ItemStack item;
if (tag.contains("item", Tag.TAG_STRING) && !tag.contains(TAG_STACK, Tag.TAG_COMPOUND)) {
item = new ItemStack(ForgeRegistries.ITEMS.getValue(new ResourceLocation(tag.getString("item"))));
} else {
item = ItemStack.of(tag.getCompound(TAG_STACK));
}
var uuid = tag.getUUID(TAG_OWNER); var uuid = tag.getUUID(TAG_OWNER);
return new FrozenColorizer(item, uuid); return new FrozenColorizer(item, uuid);
} catch (NullPointerException exn) { } catch (NullPointerException exn) {

View file

@ -362,12 +362,10 @@ class CastingHarness private constructor(
@JvmStatic @JvmStatic
fun DeserializeFromNBT(nbt: Tag, ctx: CastingContext): CastingHarness { fun DeserializeFromNBT(nbt: Tag, ctx: CastingContext): CastingHarness {
return try { return try {
val nbt = nbt as CompoundTag
val stack = mutableListOf<SpellDatum<*>>() val stack = mutableListOf<SpellDatum<*>>()
val stackTag = nbt.getList(TAG_STACK, Tag.TAG_COMPOUND.toInt()) val stackTag = (nbt as CompoundTag).getList(TAG_STACK, Tag.TAG_COMPOUND.toInt())
for (subtag in stackTag) { for (subtag in stackTag) {
val datum = SpellDatum.DeserializeFromNBT(subtag as CompoundTag, ctx) val datum = SpellDatum.DeserializeFromNBT(subtag as CompoundTag, ctx.world)
stack.add(datum) stack.add(datum)
} }

View file

@ -1,9 +1,9 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.spell.mishaps
import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.ParticleSpray import at.petrak.hexcasting.api.spell.ParticleSpray
import at.petrak.hexcasting.api.spell.SpellDatum import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.utils.HexDamageSources import at.petrak.hexcasting.api.utils.HexDamageSources
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.world.entity.npc.Villager import net.minecraft.world.entity.npc.Villager
@ -11,7 +11,7 @@ import net.minecraft.world.item.DyeColor
class MishapAlreadyBrainswept(val villager: Villager) : Mishap() { class MishapAlreadyBrainswept(val villager: Villager) : Mishap() {
override fun accentColor(ctx: CastingContext, errorCtx: Context): FrozenColorizer = override fun accentColor(ctx: CastingContext, errorCtx: Context): FrozenColorizer =
dyeColor(DyeColor.LIME) dyeColor(DyeColor.GREEN)
override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<SpellDatum<*>>) { override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<SpellDatum<*>>) {
villager.hurt(HexDamageSources.OVERCAST, villager.health) villager.hurt(HexDamageSources.OVERCAST, villager.health)

View file

@ -13,7 +13,7 @@ import net.minecraft.world.phys.Vec3
class MishapBadBrainsweep(val villager: Villager, val pos: BlockPos) : Mishap() { class MishapBadBrainsweep(val villager: Villager, val pos: BlockPos) : Mishap() {
override fun accentColor(ctx: CastingContext, errorCtx: Context): FrozenColorizer = override fun accentColor(ctx: CastingContext, errorCtx: Context): FrozenColorizer =
dyeColor(DyeColor.LIME) dyeColor(DyeColor.GREEN)
override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<SpellDatum<*>>) { override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<SpellDatum<*>>) {
villager.hurt(HexDamageSources.OVERCAST, villager.health) villager.hurt(HexDamageSources.OVERCAST, villager.health)

View file

@ -1,30 +1,31 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.spell.mishaps
import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.SpellDatum import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.misc.FrozenColorizer
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.network.chat.TranslatableComponent import net.minecraft.network.chat.TranslatableComponent
import net.minecraft.world.entity.item.ItemEntity
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
import net.minecraft.world.item.ItemStack
class MishapBadItem(val item: ItemStack, val wanted: Component) : Mishap() { class MishapBadItem(val item: ItemEntity, val wanted: Component) : Mishap() {
override fun accentColor(ctx: CastingContext, errorCtx: Context): FrozenColorizer = override fun accentColor(ctx: CastingContext, errorCtx: Context): FrozenColorizer =
dyeColor(DyeColor.BROWN) dyeColor(DyeColor.BROWN)
override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<SpellDatum<*>>) { override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<SpellDatum<*>>) {
// not really sure what to do here? item.deltaMovement = item.deltaMovement.add((Math.random() - 0.5) * 0.05, 1.0, (Math.random() - 0.5) * 0.05)
} }
override fun errorMessage(ctx: CastingContext, errorCtx: Context): Component { override fun errorMessage(ctx: CastingContext, errorCtx: Context): Component {
if (item.isEmpty) return if (item.item.isEmpty)
error("no_item", actionName(errorCtx.action), wanted) error("no_item", actionName(errorCtx.action), wanted)
return error("bad_item", actionName(errorCtx.action), wanted, item) else
error("bad_item", actionName(errorCtx.action), wanted, item.item)
} }
companion object { companion object {
@JvmStatic @JvmStatic
fun of(item: ItemStack, stub: String): MishapBadItem { fun of(item: ItemEntity, stub: String): MishapBadItem {
return MishapBadItem(item, TranslatableComponent("hexcasting.mishap.bad_item.$stub")) return MishapBadItem(item, TranslatableComponent("hexcasting.mishap.bad_item.$stub"))
} }
} }

View file

@ -1,5 +1,6 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.spell.mishaps
import at.petrak.hexcasting.api.item.CasterItem
import at.petrak.hexcasting.api.spell.SpellDatum import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
@ -15,12 +16,12 @@ class MishapEntityTooFarAway(val entity: Entity) : Mishap() {
override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<SpellDatum<*>>) { override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<SpellDatum<*>>) {
// Knock the player's items out of their hands // Knock the player's items out of their hands
val items = listOf( val items = mutableListOf<ItemStack>()
ctx.caster.mainHandItem.copy(),
ctx.caster.offhandItem.copy()
)
for (hand in InteractionHand.values()) { for (hand in InteractionHand.values()) {
ctx.caster.setItemInHand(hand, ItemStack.EMPTY.copy()) if (hand != ctx.castingHand || ctx.caster.getItemInHand(hand).item !is CasterItem) {
items.add(ctx.caster.getItemInHand(hand).copy())
ctx.caster.setItemInHand(hand, ItemStack.EMPTY)
}
} }
val delta = entity.position().subtract(ctx.position).normalize().scale(0.5) val delta = entity.position().subtract(ctx.position).normalize().scale(0.5)

View file

@ -1,5 +1,6 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.spell.mishaps
import at.petrak.hexcasting.api.item.CasterItem
import at.petrak.hexcasting.api.spell.SpellDatum import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.misc.FrozenColorizer import at.petrak.hexcasting.api.misc.FrozenColorizer
@ -15,12 +16,12 @@ class MishapLocationTooFarAway(val location: Vec3) : Mishap() {
override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<SpellDatum<*>>) { override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<SpellDatum<*>>) {
// Knock the player's items out of their hands // Knock the player's items out of their hands
val items = listOf( val items = mutableListOf<ItemStack>()
ctx.caster.mainHandItem.copy(),
ctx.caster.offhandItem.copy()
)
for (hand in InteractionHand.values()) { for (hand in InteractionHand.values()) {
ctx.caster.setItemInHand(hand, ItemStack.EMPTY.copy()) if (hand != ctx.castingHand || ctx.caster.getItemInHand(hand).item !is CasterItem) {
items.add(ctx.caster.getItemInHand(hand).copy())
ctx.caster.setItemInHand(hand, ItemStack.EMPTY)
}
} }
val delta = location.subtract(ctx.position).normalize().scale(0.5) val delta = location.subtract(ctx.position).normalize().scale(0.5)

View file

@ -1,14 +1,14 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.spell.mishaps
import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.SpellDatum import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.misc.FrozenColorizer
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
class MishapNoSpellCircle : Mishap() { class MishapNoSpellCircle : Mishap() {
override fun accentColor(ctx: CastingContext, errorCtx: Context): FrozenColorizer = override fun accentColor(ctx: CastingContext, errorCtx: Context): FrozenColorizer =
dyeColor(DyeColor.PURPLE) dyeColor(DyeColor.LIGHT_BLUE)
override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<SpellDatum<*>>) { override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<SpellDatum<*>>) {
ctx.caster.inventory.dropAll() ctx.caster.inventory.dropAll()

View file

@ -1,8 +1,8 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.spell.mishaps
import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.SpellDatum import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.misc.FrozenColorizer
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.world.effect.MobEffectInstance import net.minecraft.world.effect.MobEffectInstance
import net.minecraft.world.effect.MobEffects import net.minecraft.world.effect.MobEffects
@ -11,7 +11,7 @@ import net.minecraft.world.item.DyeColor
class MishapOthersName(val other: Player) : Mishap() { class MishapOthersName(val other: Player) : Mishap() {
override fun accentColor(ctx: CastingContext, errorCtx: Context): FrozenColorizer = override fun accentColor(ctx: CastingContext, errorCtx: Context): FrozenColorizer =
dyeColor(DyeColor.ORANGE) dyeColor(DyeColor.BLACK)
override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<SpellDatum<*>>) { override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<SpellDatum<*>>) {
val effect = MobEffectInstance(MobEffects.BLINDNESS, 20 * 60) val effect = MobEffectInstance(MobEffects.BLINDNESS, 20 * 60)

View file

@ -1,14 +1,14 @@
package at.petrak.hexcasting.api.spell.mishaps package at.petrak.hexcasting.api.spell.mishaps
import at.petrak.hexcasting.api.misc.FrozenColorizer
import at.petrak.hexcasting.api.spell.SpellDatum import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.misc.FrozenColorizer
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.world.item.DyeColor import net.minecraft.world.item.DyeColor
class MishapTooManyCloseParens : Mishap() { class MishapTooManyCloseParens : Mishap() {
override fun accentColor(ctx: CastingContext, errorCtx: Context): FrozenColorizer = override fun accentColor(ctx: CastingContext, errorCtx: Context): FrozenColorizer =
dyeColor(DyeColor.PINK) dyeColor(DyeColor.ORANGE)
override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<SpellDatum<*>>) { override fun execute(ctx: CastingContext, errorCtx: Context, stack: MutableList<SpellDatum<*>>) {
stack.add(SpellDatum.make(errorCtx.pattern)) stack.add(SpellDatum.make(errorCtx.pattern))

View file

@ -71,7 +71,6 @@ object RenderLib {
val n = points.size val n = points.size
for ((i, pair) in points.zipWithNext().withIndex()) { for ((i, pair) in points.zipWithNext().withIndex()) {
val i = i.toFloat()
val (p1, p2) = pair val (p1, p2) = pair
// https://github.com/not-fl3/macroquad/blob/master/src/shapes.rs#L163 // https://github.com/not-fl3/macroquad/blob/master/src/shapes.rs#L163
// GuiComponent::innerFill line 52 // GuiComponent::innerFill line 52
@ -89,8 +88,8 @@ object RenderLib {
fun color(time: Float): BlockPos = fun color(time: Float): BlockPos =
BlockPos(Mth.lerp(time, r1, r2).toInt(), Mth.lerp(time, g1, g2).toInt(), Mth.lerp(time, b1, b2).toInt()) BlockPos(Mth.lerp(time, r1, r2).toInt(), Mth.lerp(time, g1, g2).toInt(), Mth.lerp(time, b1, b2).toInt())
val color1 = color(i / n) val color1 = color(i.toFloat() / n)
val color2 = color((i + 1) / n) val color2 = color((i + 1f) / n)
buf.vertex(mat, p1.x + tx, p1.y + ty, z).color(color1.x, color1.y, color1.z, a).endVertex() buf.vertex(mat, p1.x + tx, p1.y + ty, z).color(color1.x, color1.y, color1.z, a).endVertex()
buf.vertex(mat, p1.x - tx, p1.y - ty, z).color(color1.x, color1.y, color1.z, a).endVertex() buf.vertex(mat, p1.x - tx, p1.y - ty, z).color(color1.x, color1.y, color1.z, a).endVertex()
buf.vertex(mat, p2.x + tx, p2.y + ty, z).color(color2.x, color2.y, color2.z, a).endVertex() buf.vertex(mat, p2.x + tx, p2.y + ty, z).color(color2.x, color2.y, color2.z, a).endVertex()

View file

@ -128,9 +128,9 @@ public class RegisterPatterns {
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("qq", HexDir.SOUTH_WEST), prefix("less_eq"), PatternRegistry.mapPattern(HexPattern.FromAnglesSig("qq", HexDir.SOUTH_WEST), prefix("less_eq"),
new OpCompare((a, b) -> a <= b)); new OpCompare((a, b) -> a <= b));
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("ad", HexDir.EAST), prefix("equals"), PatternRegistry.mapPattern(HexPattern.FromAnglesSig("ad", HexDir.EAST), prefix("equals"),
new OpCompare((a, b) -> Math.abs(a - b) < 0.0001)); new OpEquality(false));
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("da", HexDir.EAST), prefix("not_equals"), PatternRegistry.mapPattern(HexPattern.FromAnglesSig("da", HexDir.EAST), prefix("not_equals"),
new OpCompare((a, b) -> Math.abs(a - b) >= 0.0001)); new OpEquality(true));
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("dw", HexDir.NORTH_WEST), prefix("not"), PatternRegistry.mapPattern(HexPattern.FromAnglesSig("dw", HexDir.NORTH_WEST), prefix("not"),
OpNot.INSTANCE); OpNot.INSTANCE);
PatternRegistry.mapPattern(HexPattern.FromAnglesSig("aw", HexDir.NORTH_EAST), prefix("identity"), PatternRegistry.mapPattern(HexPattern.FromAnglesSig("aw", HexDir.NORTH_EAST), prefix("identity"),

View file

@ -1,10 +1,10 @@
package at.petrak.hexcasting.common.casting.operators package at.petrak.hexcasting.common.casting.operators
import at.petrak.hexcasting.api.cap.HexCapabilities
import at.petrak.hexcasting.api.spell.ConstManaOperator import at.petrak.hexcasting.api.spell.ConstManaOperator
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
import at.petrak.hexcasting.api.spell.SpellDatum import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.cap.HexCapabilities
import at.petrak.hexcasting.api.spell.mishaps.MishapBadItem import at.petrak.hexcasting.api.spell.mishaps.MishapBadItem
import net.minecraft.world.entity.item.ItemEntity import net.minecraft.world.entity.item.ItemEntity
@ -19,14 +19,14 @@ object OpTheCoolerRead : ConstManaOperator {
val stack = target.item val stack = target.item
val datumHolder = stack.getCapability(HexCapabilities.DATUM).resolve() val datumHolder = stack.getCapability(HexCapabilities.DATUM).resolve()
if (!datumHolder.isPresent) if (!datumHolder.isPresent)
throw MishapBadItem.of(stack, "iota.read") throw MishapBadItem.of(target, "iota.read")
ctx.assertEntityInRange(target) ctx.assertEntityInRange(target)
val datum = datumHolder.get().readDatum(ctx.world) val datum = datumHolder.get().readDatum(ctx.world)
?: datumHolder.get().emptyDatum() ?: datumHolder.get().emptyDatum()
?: throw MishapBadItem.of(stack, "iota.read") ?: throw MishapBadItem.of(target, "iota.read")
return listOf(datum) return listOf(datum)
} }
} }

View file

@ -0,0 +1,35 @@
package at.petrak.hexcasting.common.casting.operators.math.logic
import at.petrak.hexcasting.api.spell.ConstManaOperator
import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext
import net.minecraft.world.phys.Vec3
import kotlin.math.abs
class OpEquality(val invert: Boolean) : ConstManaOperator {
override val argc = 2
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
val lhs = args[0]
val rhs = args[1]
return spellListOf(if (checkEquals(lhs.payload, rhs.payload) != invert) 1.0 else 0.0)
}
private fun checkEquals(a: Any, b: Any, recursionsLeft: Int = 64): Boolean {
return when {
a is Double && b is Double -> abs(a - b) < 0.0001
a is Vec3 && b is Vec3 -> a.subtract(b).lengthSqr() < 0.0000001
a is List<*> && b is List<*> -> {
if (a.size != b.size || recursionsLeft == 0)
return false
for (i in a.indices)
if (!checkEquals((a[i] as SpellDatum<*>).payload, (b[i] as SpellDatum<*>).payload, recursionsLeft - 1))
return false
true
}
else -> a == b
}
}
}

View file

@ -5,6 +5,7 @@ import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
import at.petrak.hexcasting.api.spell.SpellDatum import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.Widget import at.petrak.hexcasting.api.spell.Widget
import net.minecraft.world.phys.Vec3
object OpIdentityKindOf : ConstManaOperator { object OpIdentityKindOf : ConstManaOperator {
override val argc = 1 override val argc = 1
@ -13,7 +14,7 @@ object OpIdentityKindOf : ConstManaOperator {
return spellListOf( return spellListOf(
when (args[0].payload) { when (args[0].payload) {
Widget.NULL -> 0.0 Widget.NULL -> 0.0
0.0 -> Widget.NULL 0.0, Vec3.ZERO -> Widget.NULL
else -> args[0].payload else -> args[0].payload
} }
) )

View file

@ -5,12 +5,13 @@ import at.petrak.hexcasting.api.spell.Operator.Companion.spellListOf
import at.petrak.hexcasting.api.spell.SpellDatum import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.Widget import at.petrak.hexcasting.api.spell.Widget
import net.minecraft.world.phys.Vec3
object OpNot : ConstManaOperator { object OpNot : ConstManaOperator {
override val argc = 1 override val argc = 1
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> { override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
val falsy = args[0].payload == Widget.NULL || args[0].payload == 0.0 val falsy = args[0].payload == Widget.NULL || args[0].payload == 0.0 || args[0].payload == Vec3.ZERO
return spellListOf(if (falsy) 1.0 else 0.0) return spellListOf(if (falsy) 1.0 else 0.0)
} }
} }

View file

@ -6,12 +6,8 @@ import at.petrak.hexcasting.api.spell.RenderedSpell
import at.petrak.hexcasting.api.spell.SpellDatum import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.SpellOperator import at.petrak.hexcasting.api.spell.SpellOperator
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.common.network.HexMessages
import at.petrak.hexcasting.common.network.MsgAddMotionAck
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.entity.Entity import net.minecraft.world.entity.Entity
import net.minecraft.world.phys.Vec3 import net.minecraft.world.phys.Vec3
import net.minecraftforge.network.PacketDistributor
object OpAddMotion : SpellOperator { object OpAddMotion : SpellOperator {
override val argc: Int override val argc: Int
@ -27,6 +23,7 @@ object OpAddMotion : SpellOperator {
var motionForCost = motion.lengthSqr() var motionForCost = motion.lengthSqr()
if (ctx.hasBeenGivenMotion(target)) if (ctx.hasBeenGivenMotion(target))
motionForCost++ motionForCost++
ctx.markEntityAsMotionAdded(target)
return Triple( return Triple(
Spell(target, motion), Spell(target, motion),
(motionForCost * 10_000f).toInt(), (motionForCost * 10_000f).toInt(),
@ -43,13 +40,7 @@ object OpAddMotion : SpellOperator {
private data class Spell(val target: Entity, val motion: Vec3) : RenderedSpell { private data class Spell(val target: Entity, val motion: Vec3) : RenderedSpell {
override fun cast(ctx: CastingContext) { override fun cast(ctx: CastingContext) {
if (target is ServerPlayer) { target.push(motion.x, motion.y, motion.z)
// Player movement is apparently handled on the client; who knew
// There's apparently some magic flag I can set to auto-sync it but I can't find it
HexMessages.getNetwork().send(PacketDistributor.PLAYER.with { target }, MsgAddMotionAck(motion))
}
target.deltaMovement = target.deltaMovement.add(motion)
ctx.markEntityAsMotionAdded(target)
} }
} }
} }

View file

@ -41,7 +41,7 @@ class OpConjure(val light: Boolean) : SpellOperator {
val block = if (this.light) HexBlocks.CONJURED_LIGHT else HexBlocks.CONJURED_BLOCK val block = if (this.light) HexBlocks.CONJURED_LIGHT else HexBlocks.CONJURED_BLOCK
val state = block.get().getStateForPlacement(placeContext) val state = block.get().getStateForPlacement(placeContext)
if (state != null) { if (state != null) {
ctx.world.setBlock(pos, state, 2) ctx.world.setBlock(pos, state, 5)
val colorizer = HexPlayerDataHelper.getColorizer(ctx.caster) val colorizer = HexPlayerDataHelper.getColorizer(ctx.caster)

View file

@ -6,9 +6,9 @@ import at.petrak.hexcasting.api.spell.RenderedSpell
import at.petrak.hexcasting.api.spell.SpellDatum import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.SpellOperator import at.petrak.hexcasting.api.spell.SpellOperator
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.utils.ManaHelper
import at.petrak.hexcasting.api.spell.mishaps.MishapBadItem import at.petrak.hexcasting.api.spell.mishaps.MishapBadItem
import at.petrak.hexcasting.api.spell.mishaps.MishapBadOffhandItem import at.petrak.hexcasting.api.spell.mishaps.MishapBadOffhandItem
import at.petrak.hexcasting.api.utils.ManaHelper
import at.petrak.hexcasting.common.items.HexItems import at.petrak.hexcasting.common.items.HexItems
import at.petrak.hexcasting.common.items.magic.ItemManaHolder import at.petrak.hexcasting.common.items.magic.ItemManaHolder
import net.minecraft.world.entity.item.ItemEntity import net.minecraft.world.entity.item.ItemEntity
@ -42,9 +42,14 @@ object OpMakeBattery : SpellOperator {
ctx.assertEntityInRange(entity) ctx.assertEntityInRange(entity)
if (!ManaHelper.isManaItem(entity.item) || ManaHelper.extractMana(entity.item, drainForBatteries = true, simulate = true) <= 0) { if (!ManaHelper.isManaItem(entity.item) || ManaHelper.extractMana(
throw MishapBadItem.of(
entity.item, entity.item,
drainForBatteries = true,
simulate = true
) <= 0
) {
throw MishapBadItem.of(
entity,
"mana" "mana"
) )
} }
@ -59,7 +64,10 @@ object OpMakeBattery : SpellOperator {
val entityStack = itemEntity.item.copy() val entityStack = itemEntity.item.copy()
val manaAmt = ManaHelper.extractMana(entityStack, drainForBatteries = true) val manaAmt = ManaHelper.extractMana(entityStack, drainForBatteries = true)
if (manaAmt > 0) { if (manaAmt > 0) {
ctx.caster.setItemInHand(hand, ItemManaHolder.withMana(ItemStack(HexItems.BATTERY.get()), manaAmt, manaAmt)) ctx.caster.setItemInHand(
hand,
ItemManaHolder.withMana(ItemStack(HexItems.BATTERY.get()), manaAmt, manaAmt)
)
} }
itemEntity.item = entityStack itemEntity.item = entityStack

View file

@ -1,5 +1,6 @@
package at.petrak.hexcasting.common.casting.operators.spells package at.petrak.hexcasting.common.casting.operators.spells
import at.petrak.hexcasting.api.cap.HexCapabilities
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
import at.petrak.hexcasting.api.spell.ParticleSpray import at.petrak.hexcasting.api.spell.ParticleSpray
import at.petrak.hexcasting.api.spell.RenderedSpell import at.petrak.hexcasting.api.spell.RenderedSpell
@ -7,11 +8,10 @@ import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.SpellOperator import at.petrak.hexcasting.api.spell.SpellOperator
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.spell.math.HexPattern import at.petrak.hexcasting.api.spell.math.HexPattern
import at.petrak.hexcasting.api.cap.HexCapabilities
import at.petrak.hexcasting.api.utils.ManaHelper
import at.petrak.hexcasting.api.spell.mishaps.MishapBadItem import at.petrak.hexcasting.api.spell.mishaps.MishapBadItem
import at.petrak.hexcasting.api.spell.mishaps.MishapBadOffhandItem import at.petrak.hexcasting.api.spell.mishaps.MishapBadOffhandItem
import at.petrak.hexcasting.api.spell.mishaps.MishapInvalidIota import at.petrak.hexcasting.api.spell.mishaps.MishapInvalidIota
import at.petrak.hexcasting.api.utils.ManaHelper
import at.petrak.hexcasting.common.items.magic.ItemPackagedSpell import at.petrak.hexcasting.common.items.magic.ItemPackagedSpell
import net.minecraft.network.chat.TranslatableComponent import net.minecraft.network.chat.TranslatableComponent
import net.minecraft.world.entity.item.ItemEntity import net.minecraft.world.entity.item.ItemEntity
@ -36,9 +36,14 @@ class OpMakePackagedSpell<T : ItemPackagedSpell>(val itemType: T, val cost: Int)
} }
ctx.assertEntityInRange(entity) ctx.assertEntityInRange(entity)
if (!ManaHelper.isManaItem(entity.item) || ManaHelper.extractMana(entity.item, drainForBatteries = true, simulate = true) <= 0) { if (!ManaHelper.isManaItem(entity.item) || ManaHelper.extractMana(
throw MishapBadItem.of(
entity.item, entity.item,
drainForBatteries = true,
simulate = true
) <= 0
) {
throw MishapBadItem.of(
entity,
"mana" "mana"
) )
} }

View file

@ -1,15 +1,15 @@
package at.petrak.hexcasting.common.casting.operators.spells package at.petrak.hexcasting.common.casting.operators.spells
import at.petrak.hexcasting.api.cap.HexCapabilities
import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked import at.petrak.hexcasting.api.spell.Operator.Companion.getChecked
import at.petrak.hexcasting.api.spell.ParticleSpray import at.petrak.hexcasting.api.spell.ParticleSpray
import at.petrak.hexcasting.api.spell.RenderedSpell import at.petrak.hexcasting.api.spell.RenderedSpell
import at.petrak.hexcasting.api.spell.SpellDatum import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.SpellOperator import at.petrak.hexcasting.api.spell.SpellOperator
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.cap.HexCapabilities
import at.petrak.hexcasting.api.utils.ManaHelper
import at.petrak.hexcasting.api.spell.mishaps.MishapBadItem import at.petrak.hexcasting.api.spell.mishaps.MishapBadItem
import at.petrak.hexcasting.api.spell.mishaps.MishapBadOffhandItem import at.petrak.hexcasting.api.spell.mishaps.MishapBadOffhandItem
import at.petrak.hexcasting.api.utils.ManaHelper
import net.minecraft.world.entity.item.ItemEntity import net.minecraft.world.entity.item.ItemEntity
object OpRecharge : SpellOperator { object OpRecharge : SpellOperator {
@ -37,7 +37,7 @@ object OpRecharge : SpellOperator {
if (!ManaHelper.isManaItem(entity.item)) { if (!ManaHelper.isManaItem(entity.item)) {
throw MishapBadItem.of( throw MishapBadItem.of(
entity.item, entity,
"mana" "mana"
) )
} }

View file

@ -8,13 +8,10 @@ import at.petrak.hexcasting.api.spell.SpellDatum
import at.petrak.hexcasting.api.spell.SpellOperator import at.petrak.hexcasting.api.spell.SpellOperator
import at.petrak.hexcasting.api.spell.casting.CastingContext import at.petrak.hexcasting.api.spell.casting.CastingContext
import at.petrak.hexcasting.api.player.HexPlayerDataHelper import at.petrak.hexcasting.api.player.HexPlayerDataHelper
import at.petrak.hexcasting.common.network.HexMessages
import at.petrak.hexcasting.common.network.MsgAddMotionAck
import net.minecraft.server.level.ServerPlayer import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.phys.Vec3 import net.minecraft.world.phys.Vec3
import net.minecraftforge.event.entity.living.LivingEvent import net.minecraftforge.event.entity.living.LivingEvent
import net.minecraftforge.eventbus.api.SubscribeEvent import net.minecraftforge.eventbus.api.SubscribeEvent
import net.minecraftforge.network.PacketDistributor
import kotlin.math.max import kotlin.math.max
import kotlin.math.roundToInt import kotlin.math.roundToInt
@ -60,8 +57,7 @@ object OpFlight : SpellOperator {
target.abilities.flying = true target.abilities.flying = true
target.onUpdateAbilities() target.onUpdateAbilities()
// Launch the player into the air to really emphasize the flight // Launch the player into the air to really emphasize the flight
HexMessages.getNetwork() target.push(0.0, 1.0, 0.0)
.send(PacketDistributor.PLAYER.with { target }, MsgAddMotionAck(Vec3(0.0, 1.0, 0.0)))
} }
} }

View file

@ -33,7 +33,7 @@ public class ItemSlate extends BlockItem implements DataHolderItem {
var tag = stack.getTag(); var tag = stack.getTag();
if (tag != null && tag.contains("BlockEntityTag", Tag.TAG_COMPOUND)) { if (tag != null && tag.contains("BlockEntityTag", Tag.TAG_COMPOUND)) {
var bet = tag.getCompound("BlockEntityTag"); var bet = tag.getCompound("BlockEntityTag");
return bet.contains(BlockEntitySlate.TAG_PATTERN, Tag.TAG_COMPOUND); return bet.contains(BlockEntitySlate.TAG_PATTERN, Tag.TAG_COMPOUND) && !bet.getCompound(BlockEntitySlate.TAG_PATTERN).isEmpty();
} }
return false; return false;
} }
@ -50,6 +50,8 @@ public class ItemSlate extends BlockItem implements DataHolderItem {
} }
var patTag = beTag.getCompound(BlockEntitySlate.TAG_PATTERN); var patTag = beTag.getCompound(BlockEntitySlate.TAG_PATTERN);
if (patTag.isEmpty())
return null;
var out = new CompoundTag(); var out = new CompoundTag();
out.put(SpellDatum.TAG_PATTERN, patTag); out.put(SpellDatum.TAG_PATTERN, patTag);
return out; return out;
@ -61,17 +63,12 @@ public class ItemSlate extends BlockItem implements DataHolderItem {
return false; return false;
} }
if (!stack.hasTag()) return readDatumTag(stack) == null;
return true;
var beTag = stack.getTagElement("BlockEntityTag");
return beTag == null || !beTag.contains(BlockEntitySlate.TAG_PATTERN, Tag.TAG_COMPOUND);
} }
@Override @Override
public void writeDatum(ItemStack stack, SpellDatum<?> datum) { public void writeDatum(ItemStack stack, SpellDatum<?> datum) {
if (this.canWrite(stack, datum) && datum.getPayload() instanceof HexPattern pat) { if (this.canWrite(stack, datum) && datum.getPayload() instanceof HexPattern pat) {
CompoundTag tag = stack.getOrCreateTag();
var beTag = stack.getOrCreateTagElement("BlockEntityTag"); var beTag = stack.getOrCreateTagElement("BlockEntityTag");
beTag.put(BlockEntitySlate.TAG_PATTERN, pat.serializeToNBT()); beTag.put(BlockEntitySlate.TAG_PATTERN, pat.serializeToNBT());
} }

View file

@ -28,8 +28,6 @@ public class HexMessages {
MsgNewSpellPatternAck::deserialize, MsgNewSpellPatternAck::handle); MsgNewSpellPatternAck::deserialize, MsgNewSpellPatternAck::handle);
NETWORK.registerMessage(messageIdx++, MsgShiftScrollSyn.class, MsgShiftScrollSyn::serialize, NETWORK.registerMessage(messageIdx++, MsgShiftScrollSyn.class, MsgShiftScrollSyn::serialize,
MsgShiftScrollSyn::deserialize, MsgShiftScrollSyn::handle); MsgShiftScrollSyn::deserialize, MsgShiftScrollSyn::handle);
NETWORK.registerMessage(messageIdx++, MsgAddMotionAck.class, MsgAddMotionAck::serialize,
MsgAddMotionAck::deserialize, MsgAddMotionAck::handle);
NETWORK.registerMessage(messageIdx++, MsgBlinkAck.class, MsgBlinkAck::serialize, NETWORK.registerMessage(messageIdx++, MsgBlinkAck.class, MsgBlinkAck::serialize,
MsgBlinkAck::deserialize, MsgBlinkAck::handle); MsgBlinkAck::deserialize, MsgBlinkAck::handle);
NETWORK.registerMessage(messageIdx++, MsgSentinelStatusUpdateAck.class, MsgSentinelStatusUpdateAck::serialize, NETWORK.registerMessage(messageIdx++, MsgSentinelStatusUpdateAck.class, MsgSentinelStatusUpdateAck::serialize,

View file

@ -1,42 +0,0 @@
package at.petrak.hexcasting.common.network;
import io.netty.buffer.ByteBuf;
import net.minecraft.client.Minecraft;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.network.NetworkEvent;
import java.util.function.Supplier;
/**
* Sent server->client to synchronize OpAddMotion when the target is a player.
*/
public record MsgAddMotionAck(Vec3 addedMotion) {
public static MsgAddMotionAck deserialize(ByteBuf buffer) {
var buf = new FriendlyByteBuf(buffer);
var x = buf.readDouble();
var y = buf.readDouble();
var z = buf.readDouble();
return new MsgAddMotionAck(new Vec3(x, y, z));
}
public void serialize(ByteBuf buffer) {
var buf = new FriendlyByteBuf(buffer);
buf.writeDouble(this.addedMotion.x);
buf.writeDouble(this.addedMotion.y);
buf.writeDouble(this.addedMotion.z);
}
public void handle(Supplier<NetworkEvent.Context> ctx) {
ctx.get().enqueueWork(() ->
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
var player = Minecraft.getInstance().player;
var motion = player.getDeltaMovement();
player.setDeltaMovement(motion.add(this.addedMotion));
})
);
ctx.get().setPacketHandled(true);
}
}

View file

@ -10,7 +10,7 @@ version = "${file.jarVersion}"
displayName = "Hexcasting" displayName = "Hexcasting"
displayURL = "https://github.com/gamma-delta/HexMod" displayURL = "https://github.com/gamma-delta/HexMod"
logoFile = "logo.png" logoFile = "logo.png"
credits = "Alwinfy for visual effects, proofreading, and code help; Kra3tor for sound effects; Falkory for textures; and all of Vazcord for alpha-testing and supporting me!" credits = "Falkory for textures; Wiresegal for lots of polish; Alwinfy for visual effects, proofreading, and code help; Kra3tor for sound effects; naj77 for the nice logo; and all of my wonderful patrons for supporting me!"
authors = "petrak@ (aka gamma-delta)" authors = "petrak@ (aka gamma-delta)"
description = "Cast powerful Hexes on the fly by drawing patterns with a staff." description = "Cast powerful Hexes on the fly by drawing patterns with a staff."

View file

@ -202,7 +202,7 @@
"hexcasting.spell.hexcasting:undo": "Novice's Gambit", "hexcasting.spell.hexcasting:undo": "Novice's Gambit",
"hexcasting.spell.hexcasting:const/null": "Nullary Reflection", "hexcasting.spell.hexcasting:const/null": "Nullary Reflection",
"hexcasting.spell.hexcasting:duplicate": "Gemini Decomposition", "hexcasting.spell.hexcasting:duplicate": "Gemini Decomposition",
"hexcasting.spell.hexcasting:duplicate_n": "Gemini Gambit", "hexcasting.spell.hexcasting:duplicate_n": "Gemini's Gambit",
"hexcasting.spell.hexcasting:swap": "Jester's Gambit", "hexcasting.spell.hexcasting:swap": "Jester's Gambit",
"hexcasting.spell.hexcasting:fisherman": "Fisherman's Gambit", "hexcasting.spell.hexcasting:fisherman": "Fisherman's Gambit",
"hexcasting.spell.hexcasting:swizzle": "Swindler's Gambit", "hexcasting.spell.hexcasting:swizzle": "Swindler's Gambit",
@ -418,8 +418,8 @@
"hexcasting.entry.101": "Hexing 101", "hexcasting.entry.101": "Hexing 101",
"hexcasting.page.101.1": "Casting a _Hex is quite difficult-- no wonder this art was lost to time! I'll have to re-read my notes carefully.$(br2)I can start a _Hex by pressing $(k:use) with a $(item)Staff/$ in my hand-- this will cause a hexagonal grid of dots to appear in front of me. Then I can click and drag from dot to dot to draw patterns in the _media of the grid; finishing a pattern will run its corresponding action (more on that later).", "hexcasting.page.101.1": "Casting a _Hex is quite difficult-- no wonder this art was lost to time! I'll have to re-read my notes carefully.$(br2)I can start a _Hex by pressing $(k:use) with a $(item)Staff/$ in my hand-- this will cause a hexagonal grid of dots to appear in front of me. Then I can click and drag from dot to dot to draw patterns in the _media of the grid; finishing a pattern will run its corresponding action (more on that later).",
"hexcasting.page.101.2": "Once my stack is empty once again (usually by casting a spell), the grid will disappear as the _media I've stored up is released. I can also press Escape if I want to quit early.$(br2)So how do patterns work? In short:$(li)$(italic)Patterns/$ will execute...$(li)$(italic)Actions/$, which manipulate...$(li)$(italic)The Stack/$, which is a list of...$(li)$(italic)Iotas/$, which are simply units of information.", "hexcasting.page.101.2": "Once I've drawn enough patterns to cast a spell, the grid will disappear as the _media I've stored up is released. Holding $(k:sneak) while using my staff will also clear the grid, if I don't mind the chance of mishap. (It seems that the more _media I've built up, the more likely I'll meet misfortune.)$(br2)So how do patterns work? In short:$(li)$(italic)Patterns/$ will execute...$(li)$(italic)Actions/$, which manipulate...$(li)$(italic)The Stack/$, which is a list of...$(li)$(italic)Iotas/$, which are simply units of information.",
"hexcasting.page.101.3": "First, $(thing)patterns/$. These are essential-- they're what I use to manipulate the _media around me. Certain patterns, when drawn, will cause $(thing)actions/$ to happen. Actions are what actually $(italic)do/$ the magic; all patterns influence _media in particular ways, and when those influences end up doing something useful, we call it an action.$(br2)_Media can be fickle: if I draw an invalid pattern, I'll get some garbage result on my stack (read on...)", "hexcasting.page.101.3": "First, $(thing)patterns/$. These are essential-- they're what I use to manipulate the _media around me. Certain patterns, when drawn, will cause $(thing)actions/$ to happen. Actions are what actually $(italic)do/$ the magic; all patterns influence _media in particular ways, and when those influences end up doing something useful, we call it an action.$(br2)_Media can be fickle: if I draw an invalid pattern, I'll get some garbage result somewhere on my stack (read on...)",
"hexcasting.page.101.4.header": "An Example", "hexcasting.page.101.4.header": "An Example",
"hexcasting.page.101.4": "It's interesting to note that the $(italic)rotation/$ of a pattern doesn't seem to matter at all. These two patterns both perform an action called $(l:patterns/basics#hexcasting:get_caster)$(action)Mind's Reflection/$, for example.", "hexcasting.page.101.4": "It's interesting to note that the $(italic)rotation/$ of a pattern doesn't seem to matter at all. These two patterns both perform an action called $(l:patterns/basics#hexcasting:get_caster)$(action)Mind's Reflection/$, for example.",
"hexcasting.page.101.5": "A _Hex is cast by drawing (valid) actions in sequence. Each action might do one of a few things:$(li)Gather some information about the environment, leaving it on the top of the stack;$(li)manipulate the info gathered (e.g. adding two numbers); or$(li)perform some magical effect, like summoning lightning or an explosion. (These actions are called \"spells.\")$(p)When I start casting a _Hex, it creates an empty stack. Actions manipulate the top of that stack.", "hexcasting.page.101.5": "A _Hex is cast by drawing (valid) actions in sequence. Each action might do one of a few things:$(li)Gather some information about the environment, leaving it on the top of the stack;$(li)manipulate the info gathered (e.g. adding two numbers); or$(li)perform some magical effect, like summoning lightning or an explosion. (These actions are called \"spells.\")$(p)When I start casting a _Hex, it creates an empty stack. Actions manipulate the top of that stack.",
@ -430,7 +430,7 @@
"hexcasting.page.101.10": "That aside, it doesn't seem like anyone has done much research on exactly how $(italic)much/$ any particular piece of amethyst is valued. The best I can tell, an $(item)Amethyst Shard/$ is worth about five pieces of $(item)Amethyst Dust/$, and a $(item)Charged Amethyst Crystal/$ is worth about ten.$(br2)Strangely enough, it seems like no other form of amethyst is suitable to be used in the casting of a _Hex. I suspect that whole blocks or crystals are too solid to be easily unraveled into _media.", "hexcasting.page.101.10": "That aside, it doesn't seem like anyone has done much research on exactly how $(italic)much/$ any particular piece of amethyst is valued. The best I can tell, an $(item)Amethyst Shard/$ is worth about five pieces of $(item)Amethyst Dust/$, and a $(item)Charged Amethyst Crystal/$ is worth about ten.$(br2)Strangely enough, it seems like no other form of amethyst is suitable to be used in the casting of a _Hex. I suspect that whole blocks or crystals are too solid to be easily unraveled into _media.",
"hexcasting.page.101.11": "It's also worth noting that each action will consume the _media it needs immediately, rather than all at once when the Hex finishes. Also, an action will always consume entire items-- an action that only requires one $(item)Amethyst Dust/$'s worth of _media will consume an entire $(item)Charged Amethyst Crystal/$, if that's all that's present in my inventory.$(br2)Thus, it might be a good idea to bring dust for spellcasting too-- waste not, want not...", "hexcasting.page.101.11": "It's also worth noting that each action will consume the _media it needs immediately, rather than all at once when the Hex finishes. Also, an action will always consume entire items-- an action that only requires one $(item)Amethyst Dust/$'s worth of _media will consume an entire $(item)Charged Amethyst Crystal/$, if that's all that's present in my inventory.$(br2)Thus, it might be a good idea to bring dust for spellcasting too-- waste not, want not...",
"hexcasting.page.101.12": "I should also be careful to make sure I actually have enough Amethyst in my inventory-- some old texts say that Nature is happy to use one's own mind as payment instead. They describe the feeling as awful but strangely euphoric, \"[...] an effervescent dissolution into light and energy...\"$(br)Perhaps that's why all the old practitioners of the art went mad. I can't imagine burning pieces of my mind for power is $(italic)healthy/$.", "hexcasting.page.101.12": "I should also be careful to make sure I actually have enough Amethyst in my inventory-- some old texts say that Nature is happy to use one's own mind as payment instead. They describe the feeling as awful but strangely euphoric, \"[...] an effervescent dissolution into light and energy...\"$(br)Perhaps that's why all the old practitioners of the art went mad. I can't imagine burning pieces of my mind for power is $(italic)healthy/$.",
"hexcasting.page.101.13": "Maybe something's changed, though. In my experiments, I've never managed to do it; if I run out of _media, the spell will simply fail to cast, as if some barrier is blocking it from harming me. $(br2)It would be interesting to get to the bottom of the mystery, but for now I suppose it'll keep me safe.", "hexcasting.page.101.13": "Maybe something's changed, though. In my experiments, I've never managed to do it; if I run out of _media, the spell will simply fail to cast, as if some barrier is blocking it from harming me. $(br2)It would be interesting to get to the bottom of that mystery, but for now I suppose it'll keep me safe.",
"hexcasting.page.101.14": "I have also found an amusing tidbit on why so many practitioners of magic in general seem to go mad, which I may like as some light and flavorful reading not canonical to my world.$(br2)$(italic)Content Warning: some body horror and suggestive elements./$", "hexcasting.page.101.14": "I have also found an amusing tidbit on why so many practitioners of magic in general seem to go mad, which I may like as some light and flavorful reading not canonical to my world.$(br2)$(italic)Content Warning: some body horror and suggestive elements./$",
"hexcasting.page.101.14.link_text": "Goblin Punch", "hexcasting.page.101.14.link_text": "Goblin Punch",
"hexcasting.page.101.15": "Finally, it seems spells have a maximum range of influence, about 32 blocks from my position. Trying to affect anything outside of that will cause the spell to fail.", "hexcasting.page.101.15": "Finally, it seems spells have a maximum range of influence, about 32 blocks from my position. Trying to affect anything outside of that will cause the spell to fail.",
@ -444,8 +444,32 @@
"hexcasting.entry.mishaps": "Mishaps", "hexcasting.entry.mishaps": "Mishaps",
"hexcasting.page.mishaps.1": "Unfortunately, I am not (yet) a perfect being. I make mistakes from time to time in my study and casting of _Hexes; for example, misdrawing a pattern, or trying to an invoke an action with the wrong iotas. And Nature usually doesn't look too kindly on my mistakes-- causing what is called a $(italic)mishap/$.", "hexcasting.page.mishaps.1": "Unfortunately, I am not (yet) a perfect being. I make mistakes from time to time in my study and casting of _Hexes; for example, misdrawing a pattern, or trying to an invoke an action with the wrong iotas. And Nature usually doesn't look too kindly on my mistakes-- causing what is called a $(italic)mishap/$.",
"hexcasting.page.mishaps.2": "A pattern that causes a mishap will glow red in my grid. Depending on the type of mistake, I can also expect a certain deleterious effect and a spray of sparks as the mishandled _media curdles into light of a given color.$(br2)I also get a helpful error message in my chat, but a nagging feeling tells that will change once the \"mod updates,\" whatever that means. I shouldn't rely on always having it.", "hexcasting.page.mishaps.2": "A pattern that causes a mishap will glow red in my grid. Depending on the type of mistake, I can also expect a certain deleterious effect and a spray of red and colorful sparks as the mishandled _media curdles into light of a given color.$(br2)I also get a helpful error message in my chat, but a nagging feeling tells that will change once the \"mod updates,\" whatever that means. I shouldn't rely on always having it.",
"hexcasting.page.mishaps.3": "Fortunately, although the bad effects of mishaps are certainly $(italic)annoying/$, none of them are especially destructive in the long term. Nothing better to do than dust myself off and try again ... but I should strive for perfection anyways.$(br2)Following is a list of mishaps I have compiled.", "hexcasting.page.mishaps.3": "Fortunately, although the bad effects of mishaps are certainly $(italic)annoying/$, none of them are especially destructive in the long term. Nothing better to do than dust myself off and try again ... but I should strive for better anyways.$(br2)Following is a list of mishaps I have compiled.",
"hexcasting.page.mishaps.4.title": "Invalid Pattern",
"hexcasting.page.mishaps.4": "The pattern drawn is not associated with any action.$(br2)Causes yellow sparks, and a $(item)Garbage/$ will be pushed to the top of my stack.",
"hexcasting.page.mishaps.5.title": "Not Enough Iotas",
"hexcasting.page.mishaps.5": "The action required more iotas than were on the stack.$(br2)Causes light gray sparks, and as many $(item)Garbage/$s as would be required to fill up the argument count will be pushed.",
"hexcasting.page.mishaps.6.title": "Incorrect Iota",
"hexcasting.page.mishaps.6": "The action that was executed expected an iota of a certain type for an argument, but it got something invalid. If multiple iotas are invalid, the error message will only tell me about the error deepest in the stack.$(br2)Causes dark gray sparks, and the invalid iota will be replaced with $(item)Garbage/$.",
"hexcasting.page.mishaps.7.title": "Vector Out of Ambit",
"hexcasting.page.mishaps.7": "The action tried to affect the world at a point that was out of my range.$(br2)Causes magenta sparks, and the items in my hands will be yanked out and flung towards the offending location.",
"hexcasting.page.mishaps.8.title": "Entity Out of Ambit",
"hexcasting.page.mishaps.8": "The action tried to affect an entity that was out of my range.$(br2)Causes pink sparks, and the items in my hands will be yanked out and flung towards the offending entity.",
"hexcasting.page.mishaps.9.title": "Mathematical Error",
"hexcasting.page.mishaps.9": "The action did something offensive to the laws of mathematics, such as dividing by zero.$(br2)Causes red sparks, pushes a $(item)Garbage/$ to my stack, and my mind will be ablated, stealing half the vigor I have remaining.",
"hexcasting.page.mishaps.10.title": "Incorrect Item",
"hexcasting.page.mishaps.10": "The action requires some sort of item, but the item I supplied was not suitable$(br2)Causes brown sparks. If the offending item was in my hand, it will be flung to the floor. If it was in entity form, it will be flung in the air.",
"hexcasting.page.mishaps.11.title": "Incorrect Block",
"hexcasting.page.mishaps.11": "The action requires some sort of block at a target location, but the block supplied was not suitable.$(br2)Causes bright green sparks, and causes an ephemeral explosion at the given location; it will harm me and others, but will not destroy any blocks.",
"hexcasting.page.mishaps.12.title": "Hasty Retrospection",
"hexcasting.page.mishaps.12": "I attempted to draw $(action)Retrospection/$ without first drawing $(action)Introspection/$.$(br2)Causes orange sparks, and pushes the pattern for $(action)Retrospection/$ to the stack as a pattern iota.",
"hexcasting.page.mishaps.13.title": "Delve Too Deep",
"hexcasting.page.mishaps.13": "Evaluated too many patterns from one action.$(br2)Causes dark blue sparks, and chokes all the air out of me.",
"hexcasting.page.mishaps.14.title": "Transgress Other",
"hexcasting.page.mishaps.14": "I attempted to save a reference to another player to a permanent medium.$(br2)Causes black sparks, and robs me of my sight for approximately one minute.",
"hexcasting.page.mishaps.15.title": "Invalid Iota Type",
"hexcasting.page.mishaps.15": "A bug in the mod caused an iota of an invalid type. $(l:https://https://github.com/gamma-delta/HexMod/issues)Please open a bug report!/$$(br2)Causes black sparks.",
"hexcasting.entry.stack": "Stacks", "hexcasting.entry.stack": "Stacks",
"hexcasting.page.stack.1": "A $(thing)Stack/$, also known as a \"LIFO\", is a concept borrowed from computer science. In short, it's a collection of things designed so that you can only interact with the most recently used thing.$(br2)Think of a stack of plates, where new plates are added to the top: if you want to interact with a plate halfway down the stack, you have to remove the plates above it in order to get ahold of it.", "hexcasting.page.stack.1": "A $(thing)Stack/$, also known as a \"LIFO\", is a concept borrowed from computer science. In short, it's a collection of things designed so that you can only interact with the most recently used thing.$(br2)Think of a stack of plates, where new plates are added to the top: if you want to interact with a plate halfway down the stack, you have to remove the plates above it in order to get ahold of it.",
@ -461,14 +485,23 @@
"hexcasting.entry.influences": "Influences", "hexcasting.entry.influences": "Influences",
"hexcasting.page.influences.1": "Influences are ... strange, to say the least. Whereas most iotas seem to represent something about the world, influences represent something more... abstract, or formless.$(br2)For example, one influence I've named Null seems to represent nothing at all. It's created when there isn't a suitable answer to a question asked, such as an $(l:patterns/basics#hexcasting:raycast)$(action)Archer's Distillation/$ facing the sky.", "hexcasting.page.influences.1": "Influences are ... strange, to say the least. Whereas most iotas seem to represent something about the world, influences represent something more... abstract, or formless.$(br2)For example, one influence I've named Null seems to represent nothing at all. It's created when there isn't a suitable answer to a question asked, such as an $(l:patterns/basics#hexcasting:raycast)$(action)Archer's Distillation/$ facing the sky.",
"hexcasting.page.influences.2": "In addition, I've discovered a curious triplet of influences I've named Consideration, Introspection, and Retrospection. They seem to have properties of both patterns and other influences, yet act very differently. I can use these to add patterns to my stack as iotas, instead of matching them to actions. $(l:patterns/patterns_as_iotas)My notes on the subject are here/$.", "hexcasting.page.influences.2": "In addition, I've discovered a curious triplet of influences I've named Consideration, Introspection, and Retrospection. They seem to have properties of both patterns and other influences, yet act very differently. I can use these to add patterns to my stack as iotas, instead of matching them to actions. $(l:patterns/patterns_as_iotas)My notes on the subject are here/$.",
"hexcasting.page.influences.3": "Finally, there seems to be an infinite family of influences that just seem to be a tangled mess of _media. I've named them $(action)Garbage/$, as they are completely useless. They seem to appear in my stack at random, like pests, when I drawn an invalid pattern. Turning my (admittedly very poor) ethereal senses towards them, I see only a nonsense jumble.", "hexcasting.page.influences.3": "Finally, there seems to be an infinite family of influences that just seem to be a tangled mess of _media. I've named them $(action)Garbage/$, as they are completely useless. They seem to appear in my stack at various places in response to $(l:casting/mishaps)mishaps/$. They appear to my senses as a nonsense jumble.",
"hexcasting.entry.mishaps2": "Enlightened Mishaps",
"hexcasting.page.mishaps2.1": "I have discovered new and horrifying modes of failure. I must not succumb to them.",
"hexcasting.page.mishaps2.2.title": "Inert Mindflay",
"hexcasting.page.mishaps2.2": "Attempted to flay the mind of a villager that I have either already used, or of a character not suitable for the target block.$(br2)Causes dark green sparks, and kills the subject.",
"hexcasting.page.mishaps2.3.title": "Lack Spell Circle",
"hexcasting.page.mishaps2.3": "Tried to cast an action requiring a spell circle without a spell circle.$(br2)Causes light blue sparks, and upends my inventory onto the ground.",
"hexcasting.page.mishaps2.4.title": "Lack Akashic Record",
"hexcasting.page.mishaps2.4": "Tried to access an akashic record at a location where there isn't one.$(br2)Causes purple sparks, and steals away some of my experience.",
"_comment": "Items", "_comment": "Items",
"hexcasting.entry.amethyst": "Amethyst", "hexcasting.entry.amethyst": "Amethyst",
"hexcasting.page.amethyst.1": "It seems that I'll find three different forms of amethyst when breaking a crystal inside a geode. The smallest denomination seems to be a small pile of shimmering dust, worth a relatively small amount of _media.", "hexcasting.page.amethyst.1": "It seems that I'll find three different forms of amethyst when breaking a crystal inside a geode. The smallest denomination seems to be a small pile of shimmering dust, worth a relatively small amount of _media.",
"hexcasting.page.amethyst.2": "The second is a whole shard of amethyst, of the type non-Hexers might be used to. This has about as much _media inside as five $(item)Amethyst Dust/$s.", "hexcasting.page.amethyst.2": "The second is a whole shard of amethyst, of the type non-_Hexcasters might be used to. This has about as much _media inside as five $(item)Amethyst Dust/$s.",
"hexcasting.page.amethyst.3": "Finally, I'll rarely find a large crystal crackling with energy. This has about as much _media inside as ten units of $(item)Amethyst Dust/$s (or two $(item)Amethyst Shard/$s).", "hexcasting.page.amethyst.3": "Finally, I'll rarely find a large crystal crackling with energy. This has about as much _media inside as ten units of $(item)Amethyst Dust/$s (or two $(item)Amethyst Shard/$s).",
"hexcasting.page.amethyst.4": "$(italic)The old man sighed and raised a hand toward the fire. He unlocked a part of his brain that held the memories of the mountains around them. He pulled the energies from those lands, as he learned to do in Terisia City with Drafna, Hurkyl, the archimandrite, and the other mages of the Ivory Towers. He concentrated, and the flames writhed as they rose from the logs, twisting upon themselves until they finally formed a soft smile./$", "hexcasting.page.amethyst.4": "$(italic)The old man sighed and raised a hand toward the fire. He unlocked a part of his brain that held the memories of the mountains around them. He pulled the energies from those lands, as he learned to do in Terisia City with Drafna, Hurkyl, the archimandrite, and the other mages of the Ivory Towers. He concentrated, and the flames writhed as they rose from the logs, twisting upon themselves until they finally formed a soft smile./$",
@ -745,7 +778,7 @@
"hexcasting.entry.akashic_patterns": "Akashic Patterns", "hexcasting.entry.akashic_patterns": "Akashic Patterns",
"hexcasting.page.akashic_patterns.akashic/read": "Read the iota associated with the given pattern out of the akashic library with its record at the given position. This has no range limit. Costs about one $(item)Amethyst Dust/$.", "hexcasting.page.akashic_patterns.akashic/read": "Read the iota associated with the given pattern out of the akashic library with its record at the given position. This has no range limit. Costs about one $(item)Amethyst Dust/$.",
"hexcasting.page.akashic_patterns.akashic/write": "Associate the iota with the given pattern in the akashic library with its record at the given position. Costs about one $(item)Amethyst Dust/$.", "hexcasting.page.akashic_patterns.akashic/write": "Associate the iota with the given pattern in the akashic library with its record at the given position. This $(italic)does/$ have a range limit. Costs about one $(item)Amethyst Dust/$.",
"_comment": "Normal Spells", "_comment": "Normal Spells",
@ -793,7 +826,7 @@
"hexcasting.page.hexcasting_spell.recharge.1": "Recharge a _media-containing item in my other hand. Costs about one $(item)Charged Amethyst/$.", "hexcasting.page.hexcasting_spell.recharge.1": "Recharge a _media-containing item in my other hand. Costs about one $(item)Charged Amethyst/$.",
"hexcasting.page.hexcasting_spell.recharge.2": "This spell is cast in a similar method to the crafting spells; an entity representing a dropped stack of $(item)Amethyst/$ is provided, and recharges the _media battery of the item in my other hand.$(br2)This spell $(italic)cannot/$ recharge the item farther than its original battery size.", "hexcasting.page.hexcasting_spell.recharge.2": "This spell is cast in a similar method to the crafting spells; an entity representing a dropped stack of $(item)Amethyst/$ is provided, and recharges the _media battery of the item in my other hand.$(br2)This spell $(italic)cannot/$ recharge the item farther than its original battery size.",
"hexcasting.page.hexcasting_spell.erase.1": "Clear a _Hex-containing item in my other hand. Costs about one $(item)Amethyst Dust/$.", "hexcasting.page.hexcasting_spell.erase.1": "Clear a _Hex-containing item in my other hand. Costs about one $(item)Amethyst Dust/$.",
"hexcasting.page.hexcasting_spell.erase.2": "The spell will also void all the _media stored inside the item, releasing it back to Nature and returning the item to a perfectly clean slate. This way, I can re-use $(item)Trinket/$s I have put an erroneous spell into, for example.", "hexcasting.page.hexcasting_spell.erase.2": "The spell will also void all the _media stored inside the item, releasing it back to Nature and returning the item to a perfectly clean slate. This way, I can re-use $(item)Trinket/$s I have put an erroneous spell into, for example.$(br2)This also works to clear a $(item)Focus/$ or $(item)Spellbook/$.",
"hexcasting.entry.sentinels": "Sentinels", "hexcasting.entry.sentinels": "Sentinels",
"hexcasting.page.sentinels.1": "$(italic)Hence, away! Now all is well,$(br)One aloof stand sentinel./$$(br2)A $(thing)Sentinel/$ is a mysterious force I can summon to assist in the casting of _Hexes, like a familiar or guardian spirit. It appears as a spinning geometric shape to my eyes, but is invisible to everyone else.", "hexcasting.page.sentinels.1": "$(italic)Hence, away! Now all is well,$(br)One aloof stand sentinel./$$(br2)A $(thing)Sentinel/$ is a mysterious force I can summon to assist in the casting of _Hexes, like a familiar or guardian spirit. It appears as a spinning geometric shape to my eyes, but is invisible to everyone else.",

View file

@ -3,6 +3,5 @@
"description": "hexcasting.entry.greatwork.desc", "description": "hexcasting.entry.greatwork.desc",
"icon": "minecraft:music_disc_11", "icon": "minecraft:music_disc_11",
"sortnum": 3, "sortnum": 3,
"secret": true,
"entry_color": "54398a" "entry_color": "54398a"
} }

View file

@ -13,6 +13,70 @@
{ {
"type": "patchouli:text", "type": "patchouli:text",
"text": "hexcasting.page.mishaps.2" "text": "hexcasting.page.mishaps.2"
},
{
"type": "patchouli:text",
"text": "hexcasting.page.mishaps.3"
},
{
"type": "patchouli:text",
"title": "hexcasting.page.mishaps.4.title",
"text": "hexcasting.page.mishaps.4"
},
{
"type": "patchouli:text",
"title": "hexcasting.page.mishaps.5.title",
"text": "hexcasting.page.mishaps.5"
},
{
"type": "patchouli:text",
"title": "hexcasting.page.mishaps.6.title",
"text": "hexcasting.page.mishaps.6"
},
{
"type": "patchouli:text",
"title": "hexcasting.page.mishaps.7.title",
"text": "hexcasting.page.mishaps.7"
},
{
"type": "patchouli:text",
"title": "hexcasting.page.mishaps.8.title",
"text": "hexcasting.page.mishaps.8"
},
{
"type": "patchouli:text",
"title": "hexcasting.page.mishaps.9.title",
"text": "hexcasting.page.mishaps.9"
},
{
"type": "patchouli:text",
"title": "hexcasting.page.mishaps.10.title",
"text": "hexcasting.page.mishaps.10"
},
{
"type": "patchouli:text",
"title": "hexcasting.page.mishaps.11.title",
"text": "hexcasting.page.mishaps.11"
},
{
"type": "patchouli:text",
"title": "hexcasting.page.mishaps.12.title",
"text": "hexcasting.page.mishaps.12"
},
{
"type": "patchouli:text",
"title": "hexcasting.page.mishaps.13.title",
"text": "hexcasting.page.mishaps.13"
},
{
"type": "patchouli:text",
"title": "hexcasting.page.mishaps.14.title",
"text": "hexcasting.page.mishaps.14"
},
{
"type": "patchouli:text",
"title": "hexcasting.page.mishaps.15.title",
"text": "hexcasting.page.mishaps.15"
} }
] ]
} }

View file

@ -0,0 +1,29 @@
{
"name": "hexcasting.entry.mishaps2",
"category": "hexcasting:casting",
"icon": "minecraft:flint_and_steel",
"sortnum": 3,
"advancement": "hexcasting:enlightenment",
"entry_color": "54398a",
"pages": [
{
"type": "patchouli:text",
"text": "hexcasting.page.mishaps2.1"
},
{
"type": "patchouli:text",
"title": "hexcasting.page.mishaps2.2.title",
"text": "hexcasting.page.mishaps2.2"
},
{
"type": "patchouli:text",
"title": "hexcasting.page.mishaps2.3.title",
"text": "hexcasting.page.mishaps2.3"
},
{
"type": "patchouli:text",
"title": "hexcasting.page.mishaps2.4.title",
"text": "hexcasting.page.mishaps2.4"
}
]
}

View file

@ -42,7 +42,7 @@
"type": "hexcasting:pattern", "type": "hexcasting:pattern",
"op_id": "hexcasting:equals", "op_id": "hexcasting:equals",
"anchor": "hexcasting:equals", "anchor": "hexcasting:equals",
"input": "number, number", "input": "any, any",
"output": "number", "output": "number",
"text": "hexcasting.page.logic.equals" "text": "hexcasting.page.logic.equals"
}, },
@ -50,7 +50,7 @@
"type": "hexcasting:pattern", "type": "hexcasting:pattern",
"op_id": "hexcasting:not_equals", "op_id": "hexcasting:not_equals",
"anchor": "hexcasting:not_equals", "anchor": "hexcasting:not_equals",
"input": "number, number", "input": "any, any",
"output": "number", "output": "number",
"text": "hexcasting.page.logic.not_equals" "text": "hexcasting.page.logic.not_equals"
}, },

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 37 KiB