greater patterns now aren't just spells
Akashic Read is deliberately not a greater pattern, so you can distribute trinkets based on it on a server or something
This commit is contained in:
parent
37df5d3c56
commit
4f0e390c14
9 changed files with 86 additions and 42 deletions
|
@ -7,8 +7,7 @@ import net.minecraft.world.phys.Vec3
|
||||||
/**
|
/**
|
||||||
* Manipulates the stack in some way, usually by popping some number of values off the stack
|
* Manipulates the stack in some way, usually by popping some number of values off the stack
|
||||||
* and pushing one new value.
|
* and pushing one new value.
|
||||||
* For a more "traditional" pop arguments, push return experience, see
|
* For a more "traditional" pop arguments, push return experience, see [ConstManaOperator].
|
||||||
* [SimpleOperator][at.petrak.hexcasting.api.spell.ConstManaOperator]
|
|
||||||
*
|
*
|
||||||
* Implementors MUST NOT mutate the context.
|
* Implementors MUST NOT mutate the context.
|
||||||
*/
|
*/
|
||||||
|
@ -25,10 +24,22 @@ interface Operator {
|
||||||
fun operate(continuation: SpellContinuation, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult
|
fun operate(continuation: SpellContinuation, stack: MutableList<SpellDatum<*>>, local: SpellDatum<*>, ctx: CastingContext): OperationResult
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Do you need to be enlightened to use this operator?
|
* Do you need to be enlightened to use this operator? (i.e. is this operator a Great Pattern)
|
||||||
*/
|
*/
|
||||||
val isGreat: Boolean get() = false
|
val isGreat: Boolean get() = false
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should this Great Pattern process and have side effects, even if its user isn't enlightened?
|
||||||
|
*
|
||||||
|
* The pattern itself may modify its effects based on whether the user is enlightened or not, regardless of what this value is.
|
||||||
|
*/
|
||||||
|
val alwaysProcessGreatSpell: Boolean get() = this is SpellOperator
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can this Great Pattern give you Blind Diversion?
|
||||||
|
*/
|
||||||
|
val causesBlindDiversion: Boolean get() = this is SpellOperator
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
// I see why vzakii did this: you can't raycast out to infinity!
|
// I see why vzakii did this: you can't raycast out to infinity!
|
||||||
const val MAX_DISTANCE: Double = 32.0
|
const val MAX_DISTANCE: Double = 32.0
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package at.petrak.hexcasting.api.spell
|
package at.petrak.hexcasting.api.spell
|
||||||
|
|
||||||
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||||
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
|
||||||
import at.petrak.hexcasting.api.spell.casting.OperatorSideEffect
|
import at.petrak.hexcasting.api.spell.casting.OperatorSideEffect
|
||||||
|
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
||||||
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs
|
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs
|
||||||
|
|
||||||
interface SpellOperator : Operator {
|
interface SpellOperator : Operator {
|
||||||
|
@ -25,13 +25,17 @@ interface SpellOperator : Operator {
|
||||||
val executeResult = this.execute(args, ctx) ?: return OperationResult(continuation, stack, local, listOf())
|
val executeResult = this.execute(args, ctx) ?: return OperationResult(continuation, stack, local, listOf())
|
||||||
val (spell, mana, particles) = executeResult
|
val (spell, mana, particles) = executeResult
|
||||||
|
|
||||||
val sideEffects = mutableListOf(
|
val sideEffects = mutableListOf<OperatorSideEffect>()
|
||||||
OperatorSideEffect.ConsumeMana(mana),
|
|
||||||
OperatorSideEffect.AttemptSpell(spell, this.isGreat, this.hasCastingSound(ctx), this.awardsCastingStat(ctx))
|
if (mana > 0)
|
||||||
)
|
sideEffects.add(OperatorSideEffect.ConsumeMana(mana))
|
||||||
for (spray in particles) {
|
|
||||||
|
// Don't have an effect if the caster isn't enlightened, even if processing other side effects
|
||||||
|
if (!isGreat || ctx.isCasterEnlightened)
|
||||||
|
sideEffects.add(OperatorSideEffect.AttemptSpell(spell, this.hasCastingSound(ctx), this.awardsCastingStat(ctx)))
|
||||||
|
|
||||||
|
for (spray in particles)
|
||||||
sideEffects.add(OperatorSideEffect.Particles(spray))
|
sideEffects.add(OperatorSideEffect.Particles(spray))
|
||||||
}
|
|
||||||
|
|
||||||
return OperationResult(continuation, stack, local, sideEffects)
|
return OperationResult(continuation, stack, local, sideEffects)
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,15 +147,32 @@ class CastingHarness private constructor(
|
||||||
if (!HexConfig.server().isActionAllowed(operatorIdPair.second)) {
|
if (!HexConfig.server().isActionAllowed(operatorIdPair.second)) {
|
||||||
throw MishapDisallowedSpell()
|
throw MishapDisallowedSpell()
|
||||||
}
|
}
|
||||||
val (cont2, stack2, local2, sideEffectsUnmut) = operatorIdPair.first.operate(
|
val pattern = operatorIdPair.first
|
||||||
|
|
||||||
|
val unenlightened = pattern.isGreat && !ctx.isCasterEnlightened
|
||||||
|
|
||||||
|
val sideEffects = mutableListOf<OperatorSideEffect>()
|
||||||
|
var stack2: List<SpellDatum<*>>? = null
|
||||||
|
var cont2 = continuation
|
||||||
|
|
||||||
|
if (!unenlightened || pattern.alwaysProcessGreatSpell) {
|
||||||
|
val result = pattern.operate(
|
||||||
continuation,
|
continuation,
|
||||||
this.stack.toMutableList(),
|
this.stack.toMutableList(),
|
||||||
this.localIota,
|
this.localIota,
|
||||||
this.ctx
|
this.ctx
|
||||||
)
|
)
|
||||||
this.localIota = local2
|
cont2 = result.newContinuation
|
||||||
|
stack2 = result.newStack
|
||||||
|
this.localIota = result.newLocalIota
|
||||||
|
sideEffects.addAll(result.sideEffects)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unenlightened) {
|
||||||
|
sideEffects.add(OperatorSideEffect.RequiredEnlightenment(pattern.causesBlindDiversion))
|
||||||
|
}
|
||||||
|
|
||||||
// Stick a poofy particle effect at the caster position
|
// Stick a poofy particle effect at the caster position
|
||||||
val sideEffects = sideEffectsUnmut.toMutableList()
|
|
||||||
if (this.ctx.spellCircle == null)
|
if (this.ctx.spellCircle == null)
|
||||||
sideEffects.add(
|
sideEffects.add(
|
||||||
OperatorSideEffect.Particles(
|
OperatorSideEffect.Particles(
|
||||||
|
@ -167,9 +184,11 @@ class CastingHarness private constructor(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
val fd = this.getFunctionalData().copy(
|
val fd = stack2?.let {
|
||||||
stack = stack2,
|
this.getFunctionalData().copy(
|
||||||
|
stack = it,
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return CastResult(
|
return CastResult(
|
||||||
cont2,
|
cont2,
|
||||||
|
@ -177,6 +196,7 @@ class CastingHarness private constructor(
|
||||||
ResolvedPatternType.EVALUATED,
|
ResolvedPatternType.EVALUATED,
|
||||||
sideEffects,
|
sideEffects,
|
||||||
)
|
)
|
||||||
|
|
||||||
} catch (mishap: Mishap) {
|
} catch (mishap: Mishap) {
|
||||||
return CastResult(
|
return CastResult(
|
||||||
continuation,
|
continuation,
|
||||||
|
|
|
@ -22,23 +22,28 @@ sealed class OperatorSideEffect {
|
||||||
/** Return whether to cancel all further [OperatorSideEffect] */
|
/** Return whether to cancel all further [OperatorSideEffect] */
|
||||||
abstract fun performEffect(harness: CastingHarness): Boolean
|
abstract fun performEffect(harness: CastingHarness): Boolean
|
||||||
|
|
||||||
/** Try to cast a spell */
|
data class RequiredEnlightenment(val awardStat: Boolean) : OperatorSideEffect() {
|
||||||
data class AttemptSpell(val spell: RenderedSpell, val isGreat: Boolean, val hasCastingSound: Boolean = true, val awardStat: Boolean = true) :
|
|
||||||
OperatorSideEffect() {
|
|
||||||
override fun performEffect(harness: CastingHarness): Boolean {
|
override fun performEffect(harness: CastingHarness): Boolean {
|
||||||
return if (this.isGreat && !harness.ctx.isCasterEnlightened) {
|
|
||||||
harness.ctx.caster.sendMessage(
|
harness.ctx.caster.sendMessage(
|
||||||
TranslatableComponent("hexcasting.message.cant_great_spell"),
|
TranslatableComponent("hexcasting.message.cant_great_spell"),
|
||||||
Util.NIL_UUID
|
Util.NIL_UUID
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (awardStat)
|
||||||
HexAdvancementTriggers.FAIL_GREAT_SPELL_TRIGGER.trigger(harness.ctx.caster)
|
HexAdvancementTriggers.FAIL_GREAT_SPELL_TRIGGER.trigger(harness.ctx.caster)
|
||||||
true
|
|
||||||
} else {
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Try to cast a spell */
|
||||||
|
data class AttemptSpell(val spell: RenderedSpell, val hasCastingSound: Boolean = true, val awardStat: Boolean = true) :
|
||||||
|
OperatorSideEffect() {
|
||||||
|
override fun performEffect(harness: CastingHarness): Boolean {
|
||||||
this.spell.cast(harness.ctx)
|
this.spell.cast(harness.ctx)
|
||||||
if (awardStat)
|
if (awardStat)
|
||||||
harness.ctx.caster.awardStat(HexStatistics.SPELLS_CAST)
|
harness.ctx.caster.awardStat(HexStatistics.SPELLS_CAST)
|
||||||
false
|
return false
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
package at.petrak.hexcasting.common.casting.operators.akashic
|
package at.petrak.hexcasting.common.casting.operators.akashic
|
||||||
|
|
||||||
import at.petrak.hexcasting.api.misc.ManaConstants
|
import at.petrak.hexcasting.api.misc.ManaConstants
|
||||||
import at.petrak.hexcasting.api.spell.getChecked
|
import at.petrak.hexcasting.api.spell.*
|
||||||
import at.petrak.hexcasting.api.spell.ParticleSpray
|
|
||||||
import at.petrak.hexcasting.api.spell.RenderedSpell
|
|
||||||
import at.petrak.hexcasting.api.spell.SpellDatum
|
|
||||||
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.spell.mishaps.MishapNoAkashicRecord
|
import at.petrak.hexcasting.api.spell.mishaps.MishapNoAkashicRecord
|
||||||
|
@ -19,6 +15,8 @@ import net.minecraft.world.phys.Vec3
|
||||||
object OpAkashicWrite : SpellOperator {
|
object OpAkashicWrite : SpellOperator {
|
||||||
override val argc = 3
|
override val argc = 3
|
||||||
|
|
||||||
|
override val isGreat = true
|
||||||
|
|
||||||
override fun execute(
|
override fun execute(
|
||||||
args: List<SpellDatum<*>>,
|
args: List<SpellDatum<*>>,
|
||||||
ctx: CastingContext
|
ctx: CastingContext
|
||||||
|
|
|
@ -10,6 +10,8 @@ import net.minecraft.world.phys.Vec3
|
||||||
class OpCircleBounds(val max: Boolean) : ConstManaOperator {
|
class OpCircleBounds(val max: Boolean) : ConstManaOperator {
|
||||||
override val argc = 0
|
override val argc = 0
|
||||||
|
|
||||||
|
override val isGreat = true
|
||||||
|
|
||||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
|
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
|
||||||
if (ctx.spellCircle == null)
|
if (ctx.spellCircle == null)
|
||||||
throw MishapNoSpellCircle()
|
throw MishapNoSpellCircle()
|
||||||
|
|
|
@ -10,6 +10,8 @@ import at.petrak.hexcasting.api.spell.mishaps.MishapNoSpellCircle
|
||||||
object OpImpetusDir : ConstManaOperator {
|
object OpImpetusDir : ConstManaOperator {
|
||||||
override val argc = 0
|
override val argc = 0
|
||||||
|
|
||||||
|
override val isGreat = true
|
||||||
|
|
||||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
|
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
|
||||||
if (ctx.spellCircle == null)
|
if (ctx.spellCircle == null)
|
||||||
throw MishapNoSpellCircle()
|
throw MishapNoSpellCircle()
|
||||||
|
|
|
@ -10,6 +10,8 @@ import net.minecraft.world.phys.Vec3
|
||||||
object OpImpetusPos : ConstManaOperator {
|
object OpImpetusPos : ConstManaOperator {
|
||||||
override val argc = 0
|
override val argc = 0
|
||||||
|
|
||||||
|
override val isGreat = true
|
||||||
|
|
||||||
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
|
override fun execute(args: List<SpellDatum<*>>, ctx: CastingContext): List<SpellDatum<*>> {
|
||||||
if (ctx.spellCircle == null)
|
if (ctx.spellCircle == null)
|
||||||
throw MishapNoSpellCircle()
|
throw MishapNoSpellCircle()
|
||||||
|
|
|
@ -5,8 +5,8 @@ import at.petrak.hexcasting.api.spell.Operator
|
||||||
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.casting.CastingContext
|
import at.petrak.hexcasting.api.spell.casting.CastingContext
|
||||||
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
|
||||||
import at.petrak.hexcasting.api.spell.casting.OperatorSideEffect
|
import at.petrak.hexcasting.api.spell.casting.OperatorSideEffect
|
||||||
|
import at.petrak.hexcasting.api.spell.casting.SpellContinuation
|
||||||
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs
|
import at.petrak.hexcasting.api.spell.mishaps.MishapNotEnoughArgs
|
||||||
import net.minecraft.Util
|
import net.minecraft.Util
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ object OpPrint : Operator {
|
||||||
val datum = stack[stack.lastIndex]
|
val datum = stack[stack.lastIndex]
|
||||||
return OperationResult(
|
return OperationResult(
|
||||||
continuation, stack, local, listOf(
|
continuation, stack, local, listOf(
|
||||||
OperatorSideEffect.AttemptSpell(Spell(datum), false)
|
OperatorSideEffect.AttemptSpell(Spell(datum), hasCastingSound = false, awardStat = false)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue